12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
27b5a080bSHerbert Xu /*
37b5a080bSHerbert Xu * Synchronous Cryptographic Hash operations.
47b5a080bSHerbert Xu *
57b5a080bSHerbert Xu * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
67b5a080bSHerbert Xu */
77b5a080bSHerbert Xu
83b2f6df0SHerbert Xu #include <crypto/scatterwalk.h>
942808e5dSHerbert Xu #include <linux/cryptouser.h>
107b5a080bSHerbert Xu #include <linux/err.h>
117b5a080bSHerbert Xu #include <linux/kernel.h>
127b5a080bSHerbert Xu #include <linux/module.h>
137b5a080bSHerbert Xu #include <linux/slab.h>
147b5a080bSHerbert Xu #include <linux/seq_file.h>
1542808e5dSHerbert Xu #include <linux/string.h>
16f4d663ceSSteffen Klassert #include <net/netlink.h>
177b5a080bSHerbert Xu
1842808e5dSHerbert Xu #include "hash.h"
193b2f6df0SHerbert Xu
201c799571SHerbert Xu #define MAX_SHASH_ALIGNMASK 63
211c799571SHerbert Xu
223f683d61SHerbert Xu static const struct crypto_type crypto_shash_type;
233f683d61SHerbert Xu
shash_get_stat(struct shash_alg * alg)2442808e5dSHerbert Xu static inline struct crypto_istat_hash *shash_get_stat(struct shash_alg *alg)
2542808e5dSHerbert Xu {
2642808e5dSHerbert Xu return hash_get_stat(&alg->halg);
2742808e5dSHerbert Xu }
2842808e5dSHerbert Xu
crypto_shash_errstat(struct shash_alg * alg,int err)2942808e5dSHerbert Xu static inline int crypto_shash_errstat(struct shash_alg *alg, int err)
3042808e5dSHerbert Xu {
3142808e5dSHerbert Xu return crypto_hash_errstat(&alg->halg, err);
3242808e5dSHerbert Xu }
3342808e5dSHerbert Xu
shash_no_setkey(struct crypto_shash * tfm,const u8 * key,unsigned int keylen)34c060e16dSEric Biggers int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
3557cfe44bSHerbert Xu unsigned int keylen)
3657cfe44bSHerbert Xu {
3757cfe44bSHerbert Xu return -ENOSYS;
3857cfe44bSHerbert Xu }
39c060e16dSEric Biggers EXPORT_SYMBOL_GPL(shash_no_setkey);
4057cfe44bSHerbert Xu
shash_setkey_unaligned(struct crypto_shash * tfm,const u8 * key,unsigned int keylen)417b5a080bSHerbert Xu static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
427b5a080bSHerbert Xu unsigned int keylen)
437b5a080bSHerbert Xu {
447b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm);
457b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm);
467b5a080bSHerbert Xu unsigned long absize;
477b5a080bSHerbert Xu u8 *buffer, *alignbuffer;
487b5a080bSHerbert Xu int err;
497b5a080bSHerbert Xu
5018eb8ea6SHerbert Xu absize = keylen + (alignmask & ~(crypto_tfm_ctx_alignment() - 1));
519039f3efSJia-Ju Bai buffer = kmalloc(absize, GFP_ATOMIC);
527b5a080bSHerbert Xu if (!buffer)
537b5a080bSHerbert Xu return -ENOMEM;
547b5a080bSHerbert Xu
557b5a080bSHerbert Xu alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
567b5a080bSHerbert Xu memcpy(alignbuffer, key, keylen);
577b5a080bSHerbert Xu err = shash->setkey(tfm, alignbuffer, keylen);
58453431a5SWaiman Long kfree_sensitive(buffer);
597b5a080bSHerbert Xu return err;
607b5a080bSHerbert Xu }
617b5a080bSHerbert Xu
shash_set_needkey(struct crypto_shash * tfm,struct shash_alg * alg)62ba7d7433SEric Biggers static void shash_set_needkey(struct crypto_shash *tfm, struct shash_alg *alg)
63ba7d7433SEric Biggers {
64c2881789SEric Biggers if (crypto_shash_alg_needs_key(alg))
65ba7d7433SEric Biggers crypto_shash_set_flags(tfm, CRYPTO_TFM_NEED_KEY);
66ba7d7433SEric Biggers }
67ba7d7433SEric Biggers
crypto_shash_setkey(struct crypto_shash * tfm,const u8 * key,unsigned int keylen)687b5a080bSHerbert Xu int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
697b5a080bSHerbert Xu unsigned int keylen)
707b5a080bSHerbert Xu {
717b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm);
727b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm);
739fa68f62SEric Biggers int err;
747b5a080bSHerbert Xu
757b5a080bSHerbert Xu if ((unsigned long)key & alignmask)
769fa68f62SEric Biggers err = shash_setkey_unaligned(tfm, key, keylen);
779fa68f62SEric Biggers else
789fa68f62SEric Biggers err = shash->setkey(tfm, key, keylen);
797b5a080bSHerbert Xu
80ba7d7433SEric Biggers if (unlikely(err)) {
81ba7d7433SEric Biggers shash_set_needkey(tfm, shash);
829fa68f62SEric Biggers return err;
83ba7d7433SEric Biggers }
849fa68f62SEric Biggers
859fa68f62SEric Biggers crypto_shash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
869fa68f62SEric Biggers return 0;
877b5a080bSHerbert Xu }
887b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_setkey);
897b5a080bSHerbert Xu
shash_update_unaligned(struct shash_desc * desc,const u8 * data,unsigned int len)907b5a080bSHerbert Xu static int shash_update_unaligned(struct shash_desc *desc, const u8 *data,
917b5a080bSHerbert Xu unsigned int len)
927b5a080bSHerbert Xu {
937b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm;
947b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm);
957b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm);
967b5a080bSHerbert Xu unsigned int unaligned_len = alignmask + 1 -
977b5a080bSHerbert Xu ((unsigned long)data & alignmask);
98f3569fd6SKees Cook /*
99f3569fd6SKees Cook * We cannot count on __aligned() working for large values:
100f3569fd6SKees Cook * https://patchwork.kernel.org/patch/9507697/
101f3569fd6SKees Cook */
1021c799571SHerbert Xu u8 ubuf[MAX_SHASH_ALIGNMASK * 2];
1030e2d3a12SHerbert Xu u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
1048c32c516SHerbert Xu int err;
1057b5a080bSHerbert Xu
106f3569fd6SKees Cook if (WARN_ON(buf + unaligned_len > ubuf + sizeof(ubuf)))
107f3569fd6SKees Cook return -EINVAL;
108f3569fd6SKees Cook
109f4f68993SYehuda Sadeh if (unaligned_len > len)
110f4f68993SYehuda Sadeh unaligned_len = len;
111f4f68993SYehuda Sadeh
1127b5a080bSHerbert Xu memcpy(buf, data, unaligned_len);
1138c32c516SHerbert Xu err = shash->update(desc, buf, unaligned_len);
1148c32c516SHerbert Xu memset(buf, 0, unaligned_len);
1157b5a080bSHerbert Xu
1168c32c516SHerbert Xu return err ?:
1177b5a080bSHerbert Xu shash->update(desc, data + unaligned_len, len - unaligned_len);
1187b5a080bSHerbert Xu }
1197b5a080bSHerbert Xu
crypto_shash_update(struct shash_desc * desc,const u8 * data,unsigned int len)1207b5a080bSHerbert Xu int crypto_shash_update(struct shash_desc *desc, const u8 *data,
1217b5a080bSHerbert Xu unsigned int len)
1227b5a080bSHerbert Xu {
1237b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm;
1247b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm);
1257b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm);
12642808e5dSHerbert Xu int err;
12742808e5dSHerbert Xu
12842808e5dSHerbert Xu if (IS_ENABLED(CONFIG_CRYPTO_STATS))
12942808e5dSHerbert Xu atomic64_add(len, &shash_get_stat(shash)->hash_tlen);
1307b5a080bSHerbert Xu
1317b5a080bSHerbert Xu if ((unsigned long)data & alignmask)
13242808e5dSHerbert Xu err = shash_update_unaligned(desc, data, len);
13342808e5dSHerbert Xu else
13442808e5dSHerbert Xu err = shash->update(desc, data, len);
1357b5a080bSHerbert Xu
13642808e5dSHerbert Xu return crypto_shash_errstat(shash, err);
1377b5a080bSHerbert Xu }
1387b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_update);
1397b5a080bSHerbert Xu
shash_final_unaligned(struct shash_desc * desc,u8 * out)1407b5a080bSHerbert Xu static int shash_final_unaligned(struct shash_desc *desc, u8 *out)
1417b5a080bSHerbert Xu {
1427b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm;
1437b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm);
1447b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm);
1457b5a080bSHerbert Xu unsigned int ds = crypto_shash_digestsize(tfm);
146f3569fd6SKees Cook /*
147f3569fd6SKees Cook * We cannot count on __aligned() working for large values:
148f3569fd6SKees Cook * https://patchwork.kernel.org/patch/9507697/
149f3569fd6SKees Cook */
1501c799571SHerbert Xu u8 ubuf[MAX_SHASH_ALIGNMASK + HASH_MAX_DIGESTSIZE];
1510e2d3a12SHerbert Xu u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
1527b5a080bSHerbert Xu int err;
1537b5a080bSHerbert Xu
154f3569fd6SKees Cook if (WARN_ON(buf + ds > ubuf + sizeof(ubuf)))
155f3569fd6SKees Cook return -EINVAL;
156f3569fd6SKees Cook
1577b5a080bSHerbert Xu err = shash->final(desc, buf);
1588c32c516SHerbert Xu if (err)
1598c32c516SHerbert Xu goto out;
1608c32c516SHerbert Xu
1617b5a080bSHerbert Xu memcpy(out, buf, ds);
1628c32c516SHerbert Xu
1638c32c516SHerbert Xu out:
1648c32c516SHerbert Xu memset(buf, 0, ds);
1657b5a080bSHerbert Xu return err;
1667b5a080bSHerbert Xu }
1677b5a080bSHerbert Xu
crypto_shash_final(struct shash_desc * desc,u8 * out)1687b5a080bSHerbert Xu int crypto_shash_final(struct shash_desc *desc, u8 *out)
1697b5a080bSHerbert Xu {
1707b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm;
1717b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm);
1727b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm);
17342808e5dSHerbert Xu int err;
17442808e5dSHerbert Xu
17542808e5dSHerbert Xu if (IS_ENABLED(CONFIG_CRYPTO_STATS))
17642808e5dSHerbert Xu atomic64_inc(&shash_get_stat(shash)->hash_cnt);
1777b5a080bSHerbert Xu
1787b5a080bSHerbert Xu if ((unsigned long)out & alignmask)
17942808e5dSHerbert Xu err = shash_final_unaligned(desc, out);
18042808e5dSHerbert Xu else
18142808e5dSHerbert Xu err = shash->final(desc, out);
1827b5a080bSHerbert Xu
18342808e5dSHerbert Xu return crypto_shash_errstat(shash, err);
1847b5a080bSHerbert Xu }
1857b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_final);
1867b5a080bSHerbert Xu
shash_finup_unaligned(struct shash_desc * desc,const u8 * data,unsigned int len,u8 * out)1877b5a080bSHerbert Xu static int shash_finup_unaligned(struct shash_desc *desc, const u8 *data,
1887b5a080bSHerbert Xu unsigned int len, u8 *out)
1897b5a080bSHerbert Xu {
19042808e5dSHerbert Xu return shash_update_unaligned(desc, data, len) ?:
19142808e5dSHerbert Xu shash_final_unaligned(desc, out);
1927b5a080bSHerbert Xu }
1937b5a080bSHerbert Xu
crypto_shash_finup(struct shash_desc * desc,const u8 * data,unsigned int len,u8 * out)1947b5a080bSHerbert Xu int crypto_shash_finup(struct shash_desc *desc, const u8 *data,
1957b5a080bSHerbert Xu unsigned int len, u8 *out)
1967b5a080bSHerbert Xu {
1977b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm;
1987b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm);
1997b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm);
20042808e5dSHerbert Xu int err;
20142808e5dSHerbert Xu
20242808e5dSHerbert Xu if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
20342808e5dSHerbert Xu struct crypto_istat_hash *istat = shash_get_stat(shash);
20442808e5dSHerbert Xu
20542808e5dSHerbert Xu atomic64_inc(&istat->hash_cnt);
20642808e5dSHerbert Xu atomic64_add(len, &istat->hash_tlen);
20742808e5dSHerbert Xu }
2087b5a080bSHerbert Xu
2098267adabSHerbert Xu if (((unsigned long)data | (unsigned long)out) & alignmask)
21042808e5dSHerbert Xu err = shash_finup_unaligned(desc, data, len, out);
21142808e5dSHerbert Xu else
21242808e5dSHerbert Xu err = shash->finup(desc, data, len, out);
2137b5a080bSHerbert Xu
21442808e5dSHerbert Xu
21542808e5dSHerbert Xu return crypto_shash_errstat(shash, err);
2167b5a080bSHerbert Xu }
2177b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_finup);
2187b5a080bSHerbert Xu
shash_digest_unaligned(struct shash_desc * desc,const u8 * data,unsigned int len,u8 * out)2197b5a080bSHerbert Xu static int shash_digest_unaligned(struct shash_desc *desc, const u8 *data,
2207b5a080bSHerbert Xu unsigned int len, u8 *out)
2217b5a080bSHerbert Xu {
2227b5a080bSHerbert Xu return crypto_shash_init(desc) ?:
22342808e5dSHerbert Xu shash_update_unaligned(desc, data, len) ?:
22442808e5dSHerbert Xu shash_final_unaligned(desc, out);
2257b5a080bSHerbert Xu }
2267b5a080bSHerbert Xu
crypto_shash_digest(struct shash_desc * desc,const u8 * data,unsigned int len,u8 * out)2277b5a080bSHerbert Xu int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
2287b5a080bSHerbert Xu unsigned int len, u8 *out)
2297b5a080bSHerbert Xu {
2307b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm;
2317b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm);
2327b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm);
23342808e5dSHerbert Xu int err;
23442808e5dSHerbert Xu
23542808e5dSHerbert Xu if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
23642808e5dSHerbert Xu struct crypto_istat_hash *istat = shash_get_stat(shash);
23742808e5dSHerbert Xu
23842808e5dSHerbert Xu atomic64_inc(&istat->hash_cnt);
23942808e5dSHerbert Xu atomic64_add(len, &istat->hash_tlen);
24042808e5dSHerbert Xu }
2417b5a080bSHerbert Xu
2429fa68f62SEric Biggers if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
24342808e5dSHerbert Xu err = -ENOKEY;
24442808e5dSHerbert Xu else if (((unsigned long)data | (unsigned long)out) & alignmask)
24542808e5dSHerbert Xu err = shash_digest_unaligned(desc, data, len, out);
24642808e5dSHerbert Xu else
24742808e5dSHerbert Xu err = shash->digest(desc, data, len, out);
2489fa68f62SEric Biggers
24942808e5dSHerbert Xu return crypto_shash_errstat(shash, err);
2507b5a080bSHerbert Xu }
2517b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_digest);
2527b5a080bSHerbert Xu
crypto_shash_tfm_digest(struct crypto_shash * tfm,const u8 * data,unsigned int len,u8 * out)253822a98b8SEric Biggers int crypto_shash_tfm_digest(struct crypto_shash *tfm, const u8 *data,
254822a98b8SEric Biggers unsigned int len, u8 *out)
255822a98b8SEric Biggers {
256822a98b8SEric Biggers SHASH_DESC_ON_STACK(desc, tfm);
257822a98b8SEric Biggers int err;
258822a98b8SEric Biggers
259822a98b8SEric Biggers desc->tfm = tfm;
260822a98b8SEric Biggers
261822a98b8SEric Biggers err = crypto_shash_digest(desc, data, len, out);
262822a98b8SEric Biggers
263822a98b8SEric Biggers shash_desc_zero(desc);
264822a98b8SEric Biggers
265822a98b8SEric Biggers return err;
266822a98b8SEric Biggers }
267822a98b8SEric Biggers EXPORT_SYMBOL_GPL(crypto_shash_tfm_digest);
268822a98b8SEric Biggers
shash_default_export(struct shash_desc * desc,void * out)269f592682fSHerbert Xu static int shash_default_export(struct shash_desc *desc, void *out)
270dec8b786SHerbert Xu {
271f592682fSHerbert Xu memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(desc->tfm));
272f592682fSHerbert Xu return 0;
273dec8b786SHerbert Xu }
27499d27e1cSHerbert Xu
shash_default_import(struct shash_desc * desc,const void * in)275f592682fSHerbert Xu static int shash_default_import(struct shash_desc *desc, const void *in)
27699d27e1cSHerbert Xu {
277f592682fSHerbert Xu memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(desc->tfm));
278f592682fSHerbert Xu return 0;
27999d27e1cSHerbert Xu }
280dec8b786SHerbert Xu
shash_async_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)2813b2f6df0SHerbert Xu static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
2823b2f6df0SHerbert Xu unsigned int keylen)
2833b2f6df0SHerbert Xu {
2843b2f6df0SHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(tfm);
2853b2f6df0SHerbert Xu
2863b2f6df0SHerbert Xu return crypto_shash_setkey(*ctx, key, keylen);
2873b2f6df0SHerbert Xu }
2883b2f6df0SHerbert Xu
shash_async_init(struct ahash_request * req)2893b2f6df0SHerbert Xu static int shash_async_init(struct ahash_request *req)
2903b2f6df0SHerbert Xu {
2913b2f6df0SHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
2923b2f6df0SHerbert Xu struct shash_desc *desc = ahash_request_ctx(req);
2933b2f6df0SHerbert Xu
2943b2f6df0SHerbert Xu desc->tfm = *ctx;
2953b2f6df0SHerbert Xu
2963b2f6df0SHerbert Xu return crypto_shash_init(desc);
2973b2f6df0SHerbert Xu }
2983b2f6df0SHerbert Xu
shash_ahash_update(struct ahash_request * req,struct shash_desc * desc)2997eddf95eSHerbert Xu int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc)
3003b2f6df0SHerbert Xu {
3013b2f6df0SHerbert Xu struct crypto_hash_walk walk;
3023b2f6df0SHerbert Xu int nbytes;
3033b2f6df0SHerbert Xu
3043b2f6df0SHerbert Xu for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0;
3053b2f6df0SHerbert Xu nbytes = crypto_hash_walk_done(&walk, nbytes))
3063b2f6df0SHerbert Xu nbytes = crypto_shash_update(desc, walk.data, nbytes);
3073b2f6df0SHerbert Xu
3083b2f6df0SHerbert Xu return nbytes;
3093b2f6df0SHerbert Xu }
3107eddf95eSHerbert Xu EXPORT_SYMBOL_GPL(shash_ahash_update);
3117eddf95eSHerbert Xu
shash_async_update(struct ahash_request * req)3127eddf95eSHerbert Xu static int shash_async_update(struct ahash_request *req)
3137eddf95eSHerbert Xu {
3147eddf95eSHerbert Xu return shash_ahash_update(req, ahash_request_ctx(req));
3157eddf95eSHerbert Xu }
3163b2f6df0SHerbert Xu
shash_async_final(struct ahash_request * req)3173b2f6df0SHerbert Xu static int shash_async_final(struct ahash_request *req)
3183b2f6df0SHerbert Xu {
3193b2f6df0SHerbert Xu return crypto_shash_final(ahash_request_ctx(req), req->result);
3203b2f6df0SHerbert Xu }
3213b2f6df0SHerbert Xu
shash_ahash_finup(struct ahash_request * req,struct shash_desc * desc)32266f6ce5eSHerbert Xu int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc)
32366f6ce5eSHerbert Xu {
32466f6ce5eSHerbert Xu struct crypto_hash_walk walk;
32566f6ce5eSHerbert Xu int nbytes;
32666f6ce5eSHerbert Xu
327cbc86b91SHerbert Xu nbytes = crypto_hash_walk_first(req, &walk);
328cbc86b91SHerbert Xu if (!nbytes)
329cbc86b91SHerbert Xu return crypto_shash_final(desc, req->result);
330cbc86b91SHerbert Xu
331cbc86b91SHerbert Xu do {
33266f6ce5eSHerbert Xu nbytes = crypto_hash_walk_last(&walk) ?
33366f6ce5eSHerbert Xu crypto_shash_finup(desc, walk.data, nbytes,
33466f6ce5eSHerbert Xu req->result) :
33566f6ce5eSHerbert Xu crypto_shash_update(desc, walk.data, nbytes);
336cbc86b91SHerbert Xu nbytes = crypto_hash_walk_done(&walk, nbytes);
337cbc86b91SHerbert Xu } while (nbytes > 0);
33866f6ce5eSHerbert Xu
33966f6ce5eSHerbert Xu return nbytes;
34066f6ce5eSHerbert Xu }
34166f6ce5eSHerbert Xu EXPORT_SYMBOL_GPL(shash_ahash_finup);
34266f6ce5eSHerbert Xu
shash_async_finup(struct ahash_request * req)34366f6ce5eSHerbert Xu static int shash_async_finup(struct ahash_request *req)
34466f6ce5eSHerbert Xu {
34566f6ce5eSHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
34666f6ce5eSHerbert Xu struct shash_desc *desc = ahash_request_ctx(req);
34766f6ce5eSHerbert Xu
34866f6ce5eSHerbert Xu desc->tfm = *ctx;
34966f6ce5eSHerbert Xu
35066f6ce5eSHerbert Xu return shash_ahash_finup(req, desc);
35166f6ce5eSHerbert Xu }
35266f6ce5eSHerbert Xu
shash_ahash_digest(struct ahash_request * req,struct shash_desc * desc)3537eddf95eSHerbert Xu int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc)
3543b2f6df0SHerbert Xu {
3553b2f6df0SHerbert Xu unsigned int nbytes = req->nbytes;
356b61907bbSHerbert Xu struct scatterlist *sg;
357b61907bbSHerbert Xu unsigned int offset;
3583b2f6df0SHerbert Xu int err;
3593b2f6df0SHerbert Xu
360b61907bbSHerbert Xu if (nbytes &&
361b61907bbSHerbert Xu (sg = req->src, offset = sg->offset,
36267cb60e4SEric Biggers nbytes <= min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) {
3633b2f6df0SHerbert Xu void *data;
3643b2f6df0SHerbert Xu
365aa969515SArd Biesheuvel data = kmap_local_page(sg_page(sg));
3663b2f6df0SHerbert Xu err = crypto_shash_digest(desc, data + offset, nbytes,
3673b2f6df0SHerbert Xu req->result);
368aa969515SArd Biesheuvel kunmap_local(data);
3697eddf95eSHerbert Xu } else
3707eddf95eSHerbert Xu err = crypto_shash_init(desc) ?:
37166f6ce5eSHerbert Xu shash_ahash_finup(req, desc);
3723b2f6df0SHerbert Xu
3733b2f6df0SHerbert Xu return err;
3743b2f6df0SHerbert Xu }
3757eddf95eSHerbert Xu EXPORT_SYMBOL_GPL(shash_ahash_digest);
3767eddf95eSHerbert Xu
shash_async_digest(struct ahash_request * req)3777eddf95eSHerbert Xu static int shash_async_digest(struct ahash_request *req)
3787eddf95eSHerbert Xu {
3797eddf95eSHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
3807eddf95eSHerbert Xu struct shash_desc *desc = ahash_request_ctx(req);
3817eddf95eSHerbert Xu
3827eddf95eSHerbert Xu desc->tfm = *ctx;
3837eddf95eSHerbert Xu
3847eddf95eSHerbert Xu return shash_ahash_digest(req, desc);
3857eddf95eSHerbert Xu }
3863b2f6df0SHerbert Xu
shash_async_export(struct ahash_request * req,void * out)38766f6ce5eSHerbert Xu static int shash_async_export(struct ahash_request *req, void *out)
38866f6ce5eSHerbert Xu {
38966f6ce5eSHerbert Xu return crypto_shash_export(ahash_request_ctx(req), out);
39066f6ce5eSHerbert Xu }
39166f6ce5eSHerbert Xu
shash_async_import(struct ahash_request * req,const void * in)39266f6ce5eSHerbert Xu static int shash_async_import(struct ahash_request *req, const void *in)
39366f6ce5eSHerbert Xu {
39490246e79SHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
39590246e79SHerbert Xu struct shash_desc *desc = ahash_request_ctx(req);
39690246e79SHerbert Xu
39790246e79SHerbert Xu desc->tfm = *ctx;
39890246e79SHerbert Xu
39990246e79SHerbert Xu return crypto_shash_import(desc, in);
40066f6ce5eSHerbert Xu }
40166f6ce5eSHerbert Xu
crypto_exit_shash_ops_async(struct crypto_tfm * tfm)4023b2f6df0SHerbert Xu static void crypto_exit_shash_ops_async(struct crypto_tfm *tfm)
4033b2f6df0SHerbert Xu {
4043b2f6df0SHerbert Xu struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
4053b2f6df0SHerbert Xu
4063b2f6df0SHerbert Xu crypto_free_shash(*ctx);
4073b2f6df0SHerbert Xu }
4083b2f6df0SHerbert Xu
crypto_init_shash_ops_async(struct crypto_tfm * tfm)40988056ec3SHerbert Xu int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
4103b2f6df0SHerbert Xu {
4113b2f6df0SHerbert Xu struct crypto_alg *calg = tfm->__crt_alg;
41266f6ce5eSHerbert Xu struct shash_alg *alg = __crypto_shash_alg(calg);
41388056ec3SHerbert Xu struct crypto_ahash *crt = __crypto_ahash_cast(tfm);
4143b2f6df0SHerbert Xu struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
4153b2f6df0SHerbert Xu struct crypto_shash *shash;
4163b2f6df0SHerbert Xu
4173b2f6df0SHerbert Xu if (!crypto_mod_get(calg))
4183b2f6df0SHerbert Xu return -EAGAIN;
4193b2f6df0SHerbert Xu
4203f683d61SHerbert Xu shash = crypto_create_tfm(calg, &crypto_shash_type);
4213b2f6df0SHerbert Xu if (IS_ERR(shash)) {
4223b2f6df0SHerbert Xu crypto_mod_put(calg);
4233b2f6df0SHerbert Xu return PTR_ERR(shash);
4243b2f6df0SHerbert Xu }
4253b2f6df0SHerbert Xu
4263b2f6df0SHerbert Xu *ctx = shash;
4273b2f6df0SHerbert Xu tfm->exit = crypto_exit_shash_ops_async;
4283b2f6df0SHerbert Xu
4293b2f6df0SHerbert Xu crt->init = shash_async_init;
4303b2f6df0SHerbert Xu crt->update = shash_async_update;
4313b2f6df0SHerbert Xu crt->final = shash_async_final;
43266f6ce5eSHerbert Xu crt->finup = shash_async_finup;
4333b2f6df0SHerbert Xu crt->digest = shash_async_digest;
434ba7d7433SEric Biggers if (crypto_shash_alg_has_setkey(alg))
4353b2f6df0SHerbert Xu crt->setkey = shash_async_setkey;
43600420a65SHerbert Xu
4379fa68f62SEric Biggers crypto_ahash_set_flags(crt, crypto_shash_get_flags(shash) &
4389fa68f62SEric Biggers CRYPTO_TFM_NEED_KEY);
43900420a65SHerbert Xu
44066f6ce5eSHerbert Xu crt->export = shash_async_export;
44166f6ce5eSHerbert Xu crt->import = shash_async_import;
4423b2f6df0SHerbert Xu
4433b2f6df0SHerbert Xu crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash);
4443b2f6df0SHerbert Xu
4453b2f6df0SHerbert Xu return 0;
4463b2f6df0SHerbert Xu }
4473b2f6df0SHerbert Xu
crypto_clone_shash_ops_async(struct crypto_ahash * nhash,struct crypto_ahash * hash)448ed3630b8SHerbert Xu struct crypto_ahash *crypto_clone_shash_ops_async(struct crypto_ahash *nhash,
449ed3630b8SHerbert Xu struct crypto_ahash *hash)
450ed3630b8SHerbert Xu {
451ed3630b8SHerbert Xu struct crypto_shash **nctx = crypto_ahash_ctx(nhash);
452ed3630b8SHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(hash);
453ed3630b8SHerbert Xu struct crypto_shash *shash;
454ed3630b8SHerbert Xu
455ed3630b8SHerbert Xu shash = crypto_clone_shash(*ctx);
456ed3630b8SHerbert Xu if (IS_ERR(shash)) {
457ed3630b8SHerbert Xu crypto_free_ahash(nhash);
458ed3630b8SHerbert Xu return ERR_CAST(shash);
459ed3630b8SHerbert Xu }
460ed3630b8SHerbert Xu
461ed3630b8SHerbert Xu *nctx = shash;
462ed3630b8SHerbert Xu
463ed3630b8SHerbert Xu return nhash;
464ed3630b8SHerbert Xu }
465ed3630b8SHerbert Xu
crypto_shash_exit_tfm(struct crypto_tfm * tfm)466fbce6be5SHerbert Xu static void crypto_shash_exit_tfm(struct crypto_tfm *tfm)
4677b5a080bSHerbert Xu {
468113adefcSHerbert Xu struct crypto_shash *hash = __crypto_shash_cast(tfm);
4699fa68f62SEric Biggers struct shash_alg *alg = crypto_shash_alg(hash);
470113adefcSHerbert Xu
471fbce6be5SHerbert Xu alg->exit_tfm(hash);
472fbce6be5SHerbert Xu }
473fbce6be5SHerbert Xu
crypto_shash_init_tfm(struct crypto_tfm * tfm)474fbce6be5SHerbert Xu static int crypto_shash_init_tfm(struct crypto_tfm *tfm)
475fbce6be5SHerbert Xu {
476fbce6be5SHerbert Xu struct crypto_shash *hash = __crypto_shash_cast(tfm);
477fbce6be5SHerbert Xu struct shash_alg *alg = crypto_shash_alg(hash);
478fbce6be5SHerbert Xu int err;
479fbce6be5SHerbert Xu
4809fa68f62SEric Biggers hash->descsize = alg->descsize;
4819fa68f62SEric Biggers
482ba7d7433SEric Biggers shash_set_needkey(hash, alg);
4839fa68f62SEric Biggers
484fbce6be5SHerbert Xu if (alg->exit_tfm)
485fbce6be5SHerbert Xu tfm->exit = crypto_shash_exit_tfm;
486fbce6be5SHerbert Xu
487fbce6be5SHerbert Xu if (!alg->init_tfm)
488fbce6be5SHerbert Xu return 0;
489fbce6be5SHerbert Xu
490fbce6be5SHerbert Xu err = alg->init_tfm(hash);
491fbce6be5SHerbert Xu if (err)
492fbce6be5SHerbert Xu return err;
493fbce6be5SHerbert Xu
494fbce6be5SHerbert Xu /* ->init_tfm() may have increased the descsize. */
495fbce6be5SHerbert Xu if (WARN_ON_ONCE(hash->descsize > HASH_MAX_DESCSIZE)) {
496fbce6be5SHerbert Xu if (alg->exit_tfm)
497fbce6be5SHerbert Xu alg->exit_tfm(hash);
498fbce6be5SHerbert Xu return -EINVAL;
499fbce6be5SHerbert Xu }
500fbce6be5SHerbert Xu
5017b5a080bSHerbert Xu return 0;
5027b5a080bSHerbert Xu }
5037b5a080bSHerbert Xu
crypto_shash_free_instance(struct crypto_instance * inst)50448fb3e57SEric Biggers static void crypto_shash_free_instance(struct crypto_instance *inst)
50548fb3e57SEric Biggers {
50648fb3e57SEric Biggers struct shash_instance *shash = shash_instance(inst);
50748fb3e57SEric Biggers
50848fb3e57SEric Biggers shash->free(shash);
50948fb3e57SEric Biggers }
51048fb3e57SEric Biggers
crypto_shash_report(struct sk_buff * skb,struct crypto_alg * alg)511c0f9e01dSHerbert Xu static int __maybe_unused crypto_shash_report(
512c0f9e01dSHerbert Xu struct sk_buff *skb, struct crypto_alg *alg)
513f4d663ceSSteffen Klassert {
514f4d663ceSSteffen Klassert struct crypto_report_hash rhash;
515f4d663ceSSteffen Klassert struct shash_alg *salg = __crypto_shash_alg(alg);
516f4d663ceSSteffen Klassert
51737db69e0SEric Biggers memset(&rhash, 0, sizeof(rhash));
51837db69e0SEric Biggers
51937db69e0SEric Biggers strscpy(rhash.type, "shash", sizeof(rhash.type));
5209a5467bfSMathias Krause
521f4d663ceSSteffen Klassert rhash.blocksize = alg->cra_blocksize;
522f4d663ceSSteffen Klassert rhash.digestsize = salg->digestsize;
523f4d663ceSSteffen Klassert
52437db69e0SEric Biggers return nla_put(skb, CRYPTOCFGA_REPORT_HASH, sizeof(rhash), &rhash);
525f4d663ceSSteffen Klassert }
526f4d663ceSSteffen Klassert
5277b5a080bSHerbert Xu static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
528d8c34b94SGideon Israel Dsouza __maybe_unused;
crypto_shash_show(struct seq_file * m,struct crypto_alg * alg)5297b5a080bSHerbert Xu static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
5307b5a080bSHerbert Xu {
5317b5a080bSHerbert Xu struct shash_alg *salg = __crypto_shash_alg(alg);
5327b5a080bSHerbert Xu
5337b5a080bSHerbert Xu seq_printf(m, "type : shash\n");
5347b5a080bSHerbert Xu seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
5357b5a080bSHerbert Xu seq_printf(m, "digestsize : %u\n", salg->digestsize);
5367b5a080bSHerbert Xu }
5377b5a080bSHerbert Xu
crypto_shash_report_stat(struct sk_buff * skb,struct crypto_alg * alg)53842808e5dSHerbert Xu static int __maybe_unused crypto_shash_report_stat(
53942808e5dSHerbert Xu struct sk_buff *skb, struct crypto_alg *alg)
54042808e5dSHerbert Xu {
54142808e5dSHerbert Xu return crypto_hash_report_stat(skb, alg, "shash");
54242808e5dSHerbert Xu }
54342808e5dSHerbert Xu
5447b5a080bSHerbert Xu static const struct crypto_type crypto_shash_type = {
545ac611680SHerbert Xu .extsize = crypto_alg_extsize,
5467b5a080bSHerbert Xu .init_tfm = crypto_shash_init_tfm,
54748fb3e57SEric Biggers .free = crypto_shash_free_instance,
5487b5a080bSHerbert Xu #ifdef CONFIG_PROC_FS
5497b5a080bSHerbert Xu .show = crypto_shash_show,
5507b5a080bSHerbert Xu #endif
551*b8969a1bSOndrej Mosnacek #if IS_ENABLED(CONFIG_CRYPTO_USER)
552f4d663ceSSteffen Klassert .report = crypto_shash_report,
553c0f9e01dSHerbert Xu #endif
55442808e5dSHerbert Xu #ifdef CONFIG_CRYPTO_STATS
55542808e5dSHerbert Xu .report_stat = crypto_shash_report_stat,
55642808e5dSHerbert Xu #endif
5577b5a080bSHerbert Xu .maskclear = ~CRYPTO_ALG_TYPE_MASK,
5587b5a080bSHerbert Xu .maskset = CRYPTO_ALG_TYPE_MASK,
5597b5a080bSHerbert Xu .type = CRYPTO_ALG_TYPE_SHASH,
5607b5a080bSHerbert Xu .tfmsize = offsetof(struct crypto_shash, base),
5617b5a080bSHerbert Xu };
5627b5a080bSHerbert Xu
crypto_grab_shash(struct crypto_shash_spawn * spawn,struct crypto_instance * inst,const char * name,u32 type,u32 mask)563fdfad1ffSEric Biggers int crypto_grab_shash(struct crypto_shash_spawn *spawn,
564fdfad1ffSEric Biggers struct crypto_instance *inst,
565fdfad1ffSEric Biggers const char *name, u32 type, u32 mask)
566fdfad1ffSEric Biggers {
567fdfad1ffSEric Biggers spawn->base.frontend = &crypto_shash_type;
568fdfad1ffSEric Biggers return crypto_grab_spawn(&spawn->base, inst, name, type, mask);
569fdfad1ffSEric Biggers }
570fdfad1ffSEric Biggers EXPORT_SYMBOL_GPL(crypto_grab_shash);
571fdfad1ffSEric Biggers
crypto_alloc_shash(const char * alg_name,u32 type,u32 mask)5727b5a080bSHerbert Xu struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
5737b5a080bSHerbert Xu u32 mask)
5747b5a080bSHerbert Xu {
5753f683d61SHerbert Xu return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask);
5767b5a080bSHerbert Xu }
5777b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_alloc_shash);
5787b5a080bSHerbert Xu
crypto_has_shash(const char * alg_name,u32 type,u32 mask)57985cc4243SHannes Reinecke int crypto_has_shash(const char *alg_name, u32 type, u32 mask)
58085cc4243SHannes Reinecke {
58185cc4243SHannes Reinecke return crypto_type_has_alg(alg_name, &crypto_shash_type, type, mask);
58285cc4243SHannes Reinecke }
58385cc4243SHannes Reinecke EXPORT_SYMBOL_GPL(crypto_has_shash);
58485cc4243SHannes Reinecke
crypto_clone_shash(struct crypto_shash * hash)585ed3630b8SHerbert Xu struct crypto_shash *crypto_clone_shash(struct crypto_shash *hash)
586ed3630b8SHerbert Xu {
587ed3630b8SHerbert Xu struct crypto_tfm *tfm = crypto_shash_tfm(hash);
588ed3630b8SHerbert Xu struct shash_alg *alg = crypto_shash_alg(hash);
589ed3630b8SHerbert Xu struct crypto_shash *nhash;
590ed3630b8SHerbert Xu int err;
591ed3630b8SHerbert Xu
592ed3630b8SHerbert Xu if (!crypto_shash_alg_has_setkey(alg)) {
593ed3630b8SHerbert Xu tfm = crypto_tfm_get(tfm);
594ed3630b8SHerbert Xu if (IS_ERR(tfm))
595ed3630b8SHerbert Xu return ERR_CAST(tfm);
596ed3630b8SHerbert Xu
597ed3630b8SHerbert Xu return hash;
598ed3630b8SHerbert Xu }
599ed3630b8SHerbert Xu
600ed3630b8SHerbert Xu if (!alg->clone_tfm && (alg->init_tfm || alg->base.cra_init))
601ed3630b8SHerbert Xu return ERR_PTR(-ENOSYS);
602ed3630b8SHerbert Xu
603ed3630b8SHerbert Xu nhash = crypto_clone_tfm(&crypto_shash_type, tfm);
604ed3630b8SHerbert Xu if (IS_ERR(nhash))
605ed3630b8SHerbert Xu return nhash;
606ed3630b8SHerbert Xu
607ed3630b8SHerbert Xu nhash->descsize = hash->descsize;
608ed3630b8SHerbert Xu
609ed3630b8SHerbert Xu if (alg->clone_tfm) {
610ed3630b8SHerbert Xu err = alg->clone_tfm(nhash, hash);
611ed3630b8SHerbert Xu if (err) {
612ed3630b8SHerbert Xu crypto_free_shash(nhash);
613ed3630b8SHerbert Xu return ERR_PTR(err);
614ed3630b8SHerbert Xu }
615ed3630b8SHerbert Xu }
616ed3630b8SHerbert Xu
617ed3630b8SHerbert Xu return nhash;
618ed3630b8SHerbert Xu }
61942808e5dSHerbert Xu EXPORT_SYMBOL_GPL(crypto_clone_shash);
6207b5a080bSHerbert Xu
hash_prepare_alg(struct hash_alg_common * alg)62142808e5dSHerbert Xu int hash_prepare_alg(struct hash_alg_common *alg)
6227b5a080bSHerbert Xu {
6237b5a080bSHerbert Xu struct crypto_istat_hash *istat = hash_get_stat(alg);
6249697b328SHerbert Xu struct crypto_alg *base = &alg->base;
6257b5a080bSHerbert Xu
6267b5a080bSHerbert Xu if (alg->digestsize > HASH_MAX_DIGESTSIZE)
62742808e5dSHerbert Xu return -EINVAL;
62842808e5dSHerbert Xu
62942808e5dSHerbert Xu base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
63042808e5dSHerbert Xu
63142808e5dSHerbert Xu if (IS_ENABLED(CONFIG_CRYPTO_STATS))
63242808e5dSHerbert Xu memset(istat, 0, sizeof(*istat));
63342808e5dSHerbert Xu
63442808e5dSHerbert Xu return 0;
63542808e5dSHerbert Xu }
63642808e5dSHerbert Xu
shash_prepare_alg(struct shash_alg * alg)63742808e5dSHerbert Xu static int shash_prepare_alg(struct shash_alg *alg)
63842808e5dSHerbert Xu {
63942808e5dSHerbert Xu struct crypto_alg *base = &alg->halg.base;
64042808e5dSHerbert Xu int err;
64142808e5dSHerbert Xu
64242808e5dSHerbert Xu if (alg->descsize > HASH_MAX_DESCSIZE)
6431c799571SHerbert Xu return -EINVAL;
6441c799571SHerbert Xu
6451c799571SHerbert Xu if (base->cra_alignmask > MAX_SHASH_ALIGNMASK)
64641a2e94fSEric Biggers return -EINVAL;
64741a2e94fSEric Biggers
64841a2e94fSEric Biggers if ((alg->export && !alg->import) || (alg->import && !alg->export))
64942808e5dSHerbert Xu return -EINVAL;
65042808e5dSHerbert Xu
65142808e5dSHerbert Xu err = hash_prepare_alg(&alg->halg);
65242808e5dSHerbert Xu if (err)
6537b5a080bSHerbert Xu return err;
6547b5a080bSHerbert Xu
65599d27e1cSHerbert Xu base->cra_type = &crypto_shash_type;
6568267adabSHerbert Xu base->cra_flags |= CRYPTO_ALG_TYPE_SHASH;
6578267adabSHerbert Xu
6588267adabSHerbert Xu if (!alg->finup)
6598267adabSHerbert Xu alg->finup = shash_finup_unaligned;
660f592682fSHerbert Xu if (!alg->digest)
661f592682fSHerbert Xu alg->digest = shash_digest_unaligned;
662f592682fSHerbert Xu if (!alg->export) {
66342808e5dSHerbert Xu alg->export = shash_default_export;
664f592682fSHerbert Xu alg->import = shash_default_import;
66557cfe44bSHerbert Xu alg->halg.statesize = alg->descsize;
66657cfe44bSHerbert Xu }
66799d27e1cSHerbert Xu if (!alg->setkey)
668619a6ebdSHerbert Xu alg->setkey = shash_no_setkey;
669619a6ebdSHerbert Xu
670619a6ebdSHerbert Xu return 0;
671619a6ebdSHerbert Xu }
672619a6ebdSHerbert Xu
crypto_register_shash(struct shash_alg * alg)673619a6ebdSHerbert Xu int crypto_register_shash(struct shash_alg *alg)
674619a6ebdSHerbert Xu {
675619a6ebdSHerbert Xu struct crypto_alg *base = &alg->base;
676619a6ebdSHerbert Xu int err;
677619a6ebdSHerbert Xu
678619a6ebdSHerbert Xu err = shash_prepare_alg(alg);
6797b5a080bSHerbert Xu if (err)
6807b5a080bSHerbert Xu return err;
6817b5a080bSHerbert Xu
6827b5a080bSHerbert Xu return crypto_register_alg(base);
6837b5a080bSHerbert Xu }
684c6d633a9SEric Biggers EXPORT_SYMBOL_GPL(crypto_register_shash);
6857b5a080bSHerbert Xu
crypto_unregister_shash(struct shash_alg * alg)686c6d633a9SEric Biggers void crypto_unregister_shash(struct shash_alg *alg)
6877b5a080bSHerbert Xu {
6887b5a080bSHerbert Xu crypto_unregister_alg(&alg->base);
6897b5a080bSHerbert Xu }
69050fc3e8dSJussi Kivilinna EXPORT_SYMBOL_GPL(crypto_unregister_shash);
69150fc3e8dSJussi Kivilinna
crypto_register_shashes(struct shash_alg * algs,int count)69250fc3e8dSJussi Kivilinna int crypto_register_shashes(struct shash_alg *algs, int count)
69350fc3e8dSJussi Kivilinna {
69450fc3e8dSJussi Kivilinna int i, ret;
69550fc3e8dSJussi Kivilinna
69650fc3e8dSJussi Kivilinna for (i = 0; i < count; i++) {
69750fc3e8dSJussi Kivilinna ret = crypto_register_shash(&algs[i]);
69850fc3e8dSJussi Kivilinna if (ret)
69950fc3e8dSJussi Kivilinna goto err;
70050fc3e8dSJussi Kivilinna }
70150fc3e8dSJussi Kivilinna
70250fc3e8dSJussi Kivilinna return 0;
70350fc3e8dSJussi Kivilinna
70450fc3e8dSJussi Kivilinna err:
70550fc3e8dSJussi Kivilinna for (--i; i >= 0; --i)
70650fc3e8dSJussi Kivilinna crypto_unregister_shash(&algs[i]);
70750fc3e8dSJussi Kivilinna
70850fc3e8dSJussi Kivilinna return ret;
70950fc3e8dSJussi Kivilinna }
710c6d633a9SEric Biggers EXPORT_SYMBOL_GPL(crypto_register_shashes);
71150fc3e8dSJussi Kivilinna
crypto_unregister_shashes(struct shash_alg * algs,int count)712c6d633a9SEric Biggers void crypto_unregister_shashes(struct shash_alg *algs, int count)
71350fc3e8dSJussi Kivilinna {
714c6d633a9SEric Biggers int i;
715c6d633a9SEric Biggers
71650fc3e8dSJussi Kivilinna for (i = count - 1; i >= 0; --i)
71750fc3e8dSJussi Kivilinna crypto_unregister_shash(&algs[i]);
71850fc3e8dSJussi Kivilinna }
719619a6ebdSHerbert Xu EXPORT_SYMBOL_GPL(crypto_unregister_shashes);
720619a6ebdSHerbert Xu
shash_register_instance(struct crypto_template * tmpl,struct shash_instance * inst)721619a6ebdSHerbert Xu int shash_register_instance(struct crypto_template *tmpl,
722619a6ebdSHerbert Xu struct shash_instance *inst)
723619a6ebdSHerbert Xu {
724d4fdc2dfSEric Biggers int err;
725d4fdc2dfSEric Biggers
726d4fdc2dfSEric Biggers if (WARN_ON(!inst->free))
727619a6ebdSHerbert Xu return -EINVAL;
728619a6ebdSHerbert Xu
729619a6ebdSHerbert Xu err = shash_prepare_alg(&inst->alg);
730619a6ebdSHerbert Xu if (err)
731619a6ebdSHerbert Xu return err;
732619a6ebdSHerbert Xu
733619a6ebdSHerbert Xu return crypto_register_instance(tmpl, shash_crypto_instance(inst));
734619a6ebdSHerbert Xu }
735a39c66ccSEric Biggers EXPORT_SYMBOL_GPL(shash_register_instance);
7362e4fddd8SHerbert Xu
shash_free_singlespawn_instance(struct shash_instance * inst)737a39c66ccSEric Biggers void shash_free_singlespawn_instance(struct shash_instance *inst)
738a39c66ccSEric Biggers {
7392e4fddd8SHerbert Xu crypto_drop_spawn(shash_instance_ctx(inst));
740a39c66ccSEric Biggers kfree(inst);
7412e4fddd8SHerbert Xu }
7427b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(shash_free_singlespawn_instance);
7437b5a080bSHerbert Xu
744 MODULE_LICENSE("GPL");
745 MODULE_DESCRIPTION("Synchronous cryptographic hash type");
746