xref: /linux/crypto/shash.c (revision 619a6ebd2547f3a8ec2fbc5245daaa1f2056eb32)
17b5a080bSHerbert Xu /*
27b5a080bSHerbert Xu  * Synchronous Cryptographic Hash operations.
37b5a080bSHerbert Xu  *
47b5a080bSHerbert Xu  * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
57b5a080bSHerbert Xu  *
67b5a080bSHerbert Xu  * This program is free software; you can redistribute it and/or modify it
77b5a080bSHerbert Xu  * under the terms of the GNU General Public License as published by the Free
87b5a080bSHerbert Xu  * Software Foundation; either version 2 of the License, or (at your option)
97b5a080bSHerbert Xu  * any later version.
107b5a080bSHerbert Xu  *
117b5a080bSHerbert Xu  */
127b5a080bSHerbert Xu 
133b2f6df0SHerbert Xu #include <crypto/scatterwalk.h>
147b5a080bSHerbert Xu #include <crypto/internal/hash.h>
157b5a080bSHerbert Xu #include <linux/err.h>
167b5a080bSHerbert Xu #include <linux/kernel.h>
177b5a080bSHerbert Xu #include <linux/module.h>
187b5a080bSHerbert Xu #include <linux/slab.h>
197b5a080bSHerbert Xu #include <linux/seq_file.h>
207b5a080bSHerbert Xu 
213b2f6df0SHerbert Xu #include "internal.h"
223b2f6df0SHerbert Xu 
233f683d61SHerbert Xu static const struct crypto_type crypto_shash_type;
243f683d61SHerbert Xu 
257b5a080bSHerbert Xu static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
267b5a080bSHerbert Xu 				  unsigned int keylen)
277b5a080bSHerbert Xu {
287b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
297b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
307b5a080bSHerbert Xu 	unsigned long absize;
317b5a080bSHerbert Xu 	u8 *buffer, *alignbuffer;
327b5a080bSHerbert Xu 	int err;
337b5a080bSHerbert Xu 
347b5a080bSHerbert Xu 	absize = keylen + (alignmask & ~(CRYPTO_MINALIGN - 1));
357b5a080bSHerbert Xu 	buffer = kmalloc(absize, GFP_KERNEL);
367b5a080bSHerbert Xu 	if (!buffer)
377b5a080bSHerbert Xu 		return -ENOMEM;
387b5a080bSHerbert Xu 
397b5a080bSHerbert Xu 	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
407b5a080bSHerbert Xu 	memcpy(alignbuffer, key, keylen);
417b5a080bSHerbert Xu 	err = shash->setkey(tfm, alignbuffer, keylen);
427b5a080bSHerbert Xu 	memset(alignbuffer, 0, keylen);
437b5a080bSHerbert Xu 	kfree(buffer);
447b5a080bSHerbert Xu 	return err;
457b5a080bSHerbert Xu }
467b5a080bSHerbert Xu 
477b5a080bSHerbert Xu int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
487b5a080bSHerbert Xu 			unsigned int keylen)
497b5a080bSHerbert Xu {
507b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
517b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
527b5a080bSHerbert Xu 
533751f402SHerbert Xu 	if (!shash->setkey)
543751f402SHerbert Xu 		return -ENOSYS;
553751f402SHerbert Xu 
567b5a080bSHerbert Xu 	if ((unsigned long)key & alignmask)
577b5a080bSHerbert Xu 		return shash_setkey_unaligned(tfm, key, keylen);
587b5a080bSHerbert Xu 
597b5a080bSHerbert Xu 	return shash->setkey(tfm, key, keylen);
607b5a080bSHerbert Xu }
617b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_setkey);
627b5a080bSHerbert Xu 
637b5a080bSHerbert Xu static inline unsigned int shash_align_buffer_size(unsigned len,
647b5a080bSHerbert Xu 						   unsigned long mask)
657b5a080bSHerbert Xu {
667b5a080bSHerbert Xu 	return len + (mask & ~(__alignof__(u8 __attribute__ ((aligned))) - 1));
677b5a080bSHerbert Xu }
687b5a080bSHerbert Xu 
697b5a080bSHerbert Xu static int shash_update_unaligned(struct shash_desc *desc, const u8 *data,
707b5a080bSHerbert Xu 				  unsigned int len)
717b5a080bSHerbert Xu {
727b5a080bSHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
737b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
747b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
757b5a080bSHerbert Xu 	unsigned int unaligned_len = alignmask + 1 -
767b5a080bSHerbert Xu 				     ((unsigned long)data & alignmask);
777b5a080bSHerbert Xu 	u8 buf[shash_align_buffer_size(unaligned_len, alignmask)]
787b5a080bSHerbert Xu 		__attribute__ ((aligned));
797b5a080bSHerbert Xu 
80f4f68993SYehuda Sadeh 	if (unaligned_len > len)
81f4f68993SYehuda Sadeh 		unaligned_len = len;
82f4f68993SYehuda Sadeh 
837b5a080bSHerbert Xu 	memcpy(buf, data, unaligned_len);
847b5a080bSHerbert Xu 
857b5a080bSHerbert Xu 	return shash->update(desc, buf, unaligned_len) ?:
867b5a080bSHerbert Xu 	       shash->update(desc, data + unaligned_len, len - unaligned_len);
877b5a080bSHerbert Xu }
887b5a080bSHerbert Xu 
897b5a080bSHerbert Xu int crypto_shash_update(struct shash_desc *desc, const u8 *data,
907b5a080bSHerbert Xu 			unsigned int len)
917b5a080bSHerbert Xu {
927b5a080bSHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
937b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
947b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
957b5a080bSHerbert Xu 
967b5a080bSHerbert Xu 	if ((unsigned long)data & alignmask)
977b5a080bSHerbert Xu 		return shash_update_unaligned(desc, data, len);
987b5a080bSHerbert Xu 
997b5a080bSHerbert Xu 	return shash->update(desc, data, len);
1007b5a080bSHerbert Xu }
1017b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_update);
1027b5a080bSHerbert Xu 
1037b5a080bSHerbert Xu static int shash_final_unaligned(struct shash_desc *desc, u8 *out)
1047b5a080bSHerbert Xu {
1057b5a080bSHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
1067b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
1077b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
1087b5a080bSHerbert Xu 	unsigned int ds = crypto_shash_digestsize(tfm);
1097b5a080bSHerbert Xu 	u8 buf[shash_align_buffer_size(ds, alignmask)]
1107b5a080bSHerbert Xu 		__attribute__ ((aligned));
1117b5a080bSHerbert Xu 	int err;
1127b5a080bSHerbert Xu 
1137b5a080bSHerbert Xu 	err = shash->final(desc, buf);
1147b5a080bSHerbert Xu 	memcpy(out, buf, ds);
1157b5a080bSHerbert Xu 	return err;
1167b5a080bSHerbert Xu }
1177b5a080bSHerbert Xu 
1187b5a080bSHerbert Xu int crypto_shash_final(struct shash_desc *desc, u8 *out)
1197b5a080bSHerbert Xu {
1207b5a080bSHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
1217b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
1227b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
1237b5a080bSHerbert Xu 
1247b5a080bSHerbert Xu 	if ((unsigned long)out & alignmask)
1257b5a080bSHerbert Xu 		return shash_final_unaligned(desc, out);
1267b5a080bSHerbert Xu 
1277b5a080bSHerbert Xu 	return shash->final(desc, out);
1287b5a080bSHerbert Xu }
1297b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_final);
1307b5a080bSHerbert Xu 
1317b5a080bSHerbert Xu static int shash_finup_unaligned(struct shash_desc *desc, const u8 *data,
1327b5a080bSHerbert Xu 				 unsigned int len, u8 *out)
1337b5a080bSHerbert Xu {
1347b5a080bSHerbert Xu 	return crypto_shash_update(desc, data, len) ?:
1357b5a080bSHerbert Xu 	       crypto_shash_final(desc, out);
1367b5a080bSHerbert Xu }
1377b5a080bSHerbert Xu 
1387b5a080bSHerbert Xu int crypto_shash_finup(struct shash_desc *desc, const u8 *data,
1397b5a080bSHerbert Xu 		       unsigned int len, u8 *out)
1407b5a080bSHerbert Xu {
1417b5a080bSHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
1427b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
1437b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
1447b5a080bSHerbert Xu 
1457b5a080bSHerbert Xu 	if (((unsigned long)data | (unsigned long)out) & alignmask ||
1467b5a080bSHerbert Xu 	    !shash->finup)
1477b5a080bSHerbert Xu 		return shash_finup_unaligned(desc, data, len, out);
1487b5a080bSHerbert Xu 
1497b5a080bSHerbert Xu 	return shash->finup(desc, data, len, out);
1507b5a080bSHerbert Xu }
1517b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_finup);
1527b5a080bSHerbert Xu 
1537b5a080bSHerbert Xu static int shash_digest_unaligned(struct shash_desc *desc, const u8 *data,
1547b5a080bSHerbert Xu 				  unsigned int len, u8 *out)
1557b5a080bSHerbert Xu {
1567b5a080bSHerbert Xu 	return crypto_shash_init(desc) ?:
1577b5a080bSHerbert Xu 	       crypto_shash_update(desc, data, len) ?:
1587b5a080bSHerbert Xu 	       crypto_shash_final(desc, out);
1597b5a080bSHerbert Xu }
1607b5a080bSHerbert Xu 
1617b5a080bSHerbert Xu int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
1627b5a080bSHerbert Xu 			unsigned int len, u8 *out)
1637b5a080bSHerbert Xu {
1647b5a080bSHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
1657b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
1667b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
1677b5a080bSHerbert Xu 
1687b5a080bSHerbert Xu 	if (((unsigned long)data | (unsigned long)out) & alignmask ||
1697b5a080bSHerbert Xu 	    !shash->digest)
1707b5a080bSHerbert Xu 		return shash_digest_unaligned(desc, data, len, out);
1717b5a080bSHerbert Xu 
1727b5a080bSHerbert Xu 	return shash->digest(desc, data, len, out);
1737b5a080bSHerbert Xu }
1747b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_digest);
1757b5a080bSHerbert Xu 
176dec8b786SHerbert Xu int crypto_shash_import(struct shash_desc *desc, const u8 *in)
177dec8b786SHerbert Xu {
178dec8b786SHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
179dec8b786SHerbert Xu 	struct shash_alg *alg = crypto_shash_alg(tfm);
180dec8b786SHerbert Xu 
181dec8b786SHerbert Xu 	memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(tfm));
182dec8b786SHerbert Xu 
183dec8b786SHerbert Xu 	if (alg->reinit)
184dec8b786SHerbert Xu 		alg->reinit(desc);
185dec8b786SHerbert Xu 
186dec8b786SHerbert Xu 	return 0;
187dec8b786SHerbert Xu }
188dec8b786SHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_import);
189dec8b786SHerbert Xu 
1903b2f6df0SHerbert Xu static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
1913b2f6df0SHerbert Xu 			      unsigned int keylen)
1923b2f6df0SHerbert Xu {
1933b2f6df0SHerbert Xu 	struct crypto_shash **ctx = crypto_ahash_ctx(tfm);
1943b2f6df0SHerbert Xu 
1953b2f6df0SHerbert Xu 	return crypto_shash_setkey(*ctx, key, keylen);
1963b2f6df0SHerbert Xu }
1973b2f6df0SHerbert Xu 
1983b2f6df0SHerbert Xu static int shash_async_init(struct ahash_request *req)
1993b2f6df0SHerbert Xu {
2003b2f6df0SHerbert Xu 	struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
2013b2f6df0SHerbert Xu 	struct shash_desc *desc = ahash_request_ctx(req);
2023b2f6df0SHerbert Xu 
2033b2f6df0SHerbert Xu 	desc->tfm = *ctx;
2043b2f6df0SHerbert Xu 	desc->flags = req->base.flags;
2053b2f6df0SHerbert Xu 
2063b2f6df0SHerbert Xu 	return crypto_shash_init(desc);
2073b2f6df0SHerbert Xu }
2083b2f6df0SHerbert Xu 
2093b2f6df0SHerbert Xu static int shash_async_update(struct ahash_request *req)
2103b2f6df0SHerbert Xu {
2113b2f6df0SHerbert Xu 	struct shash_desc *desc = ahash_request_ctx(req);
2123b2f6df0SHerbert Xu 	struct crypto_hash_walk walk;
2133b2f6df0SHerbert Xu 	int nbytes;
2143b2f6df0SHerbert Xu 
2153b2f6df0SHerbert Xu 	for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0;
2163b2f6df0SHerbert Xu 	     nbytes = crypto_hash_walk_done(&walk, nbytes))
2173b2f6df0SHerbert Xu 		nbytes = crypto_shash_update(desc, walk.data, nbytes);
2183b2f6df0SHerbert Xu 
2193b2f6df0SHerbert Xu 	return nbytes;
2203b2f6df0SHerbert Xu }
2213b2f6df0SHerbert Xu 
2223b2f6df0SHerbert Xu static int shash_async_final(struct ahash_request *req)
2233b2f6df0SHerbert Xu {
2243b2f6df0SHerbert Xu 	return crypto_shash_final(ahash_request_ctx(req), req->result);
2253b2f6df0SHerbert Xu }
2263b2f6df0SHerbert Xu 
2273b2f6df0SHerbert Xu static int shash_async_digest(struct ahash_request *req)
2283b2f6df0SHerbert Xu {
2293b2f6df0SHerbert Xu 	struct scatterlist *sg = req->src;
2303b2f6df0SHerbert Xu 	unsigned int offset = sg->offset;
2313b2f6df0SHerbert Xu 	unsigned int nbytes = req->nbytes;
2323b2f6df0SHerbert Xu 	int err;
2333b2f6df0SHerbert Xu 
2343b2f6df0SHerbert Xu 	if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) {
2353b2f6df0SHerbert Xu 		struct crypto_shash **ctx =
2363b2f6df0SHerbert Xu 			crypto_ahash_ctx(crypto_ahash_reqtfm(req));
2373b2f6df0SHerbert Xu 		struct shash_desc *desc = ahash_request_ctx(req);
2383b2f6df0SHerbert Xu 		void *data;
2393b2f6df0SHerbert Xu 
2403b2f6df0SHerbert Xu 		desc->tfm = *ctx;
2413b2f6df0SHerbert Xu 		desc->flags = req->base.flags;
2423b2f6df0SHerbert Xu 
2433b2f6df0SHerbert Xu 		data = crypto_kmap(sg_page(sg), 0);
2443b2f6df0SHerbert Xu 		err = crypto_shash_digest(desc, data + offset, nbytes,
2453b2f6df0SHerbert Xu 					  req->result);
2463b2f6df0SHerbert Xu 		crypto_kunmap(data, 0);
2473b2f6df0SHerbert Xu 		crypto_yield(desc->flags);
2483b2f6df0SHerbert Xu 		goto out;
2493b2f6df0SHerbert Xu 	}
2503b2f6df0SHerbert Xu 
2513b2f6df0SHerbert Xu 	err = shash_async_init(req);
2523b2f6df0SHerbert Xu 	if (err)
2533b2f6df0SHerbert Xu 		goto out;
2543b2f6df0SHerbert Xu 
2553b2f6df0SHerbert Xu 	err = shash_async_update(req);
2563b2f6df0SHerbert Xu 	if (err)
2573b2f6df0SHerbert Xu 		goto out;
2583b2f6df0SHerbert Xu 
2593b2f6df0SHerbert Xu 	err = shash_async_final(req);
2603b2f6df0SHerbert Xu 
2613b2f6df0SHerbert Xu out:
2623b2f6df0SHerbert Xu 	return err;
2633b2f6df0SHerbert Xu }
2643b2f6df0SHerbert Xu 
2653b2f6df0SHerbert Xu static void crypto_exit_shash_ops_async(struct crypto_tfm *tfm)
2663b2f6df0SHerbert Xu {
2673b2f6df0SHerbert Xu 	struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
2683b2f6df0SHerbert Xu 
2693b2f6df0SHerbert Xu 	crypto_free_shash(*ctx);
2703b2f6df0SHerbert Xu }
2713b2f6df0SHerbert Xu 
2723b2f6df0SHerbert Xu static int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
2733b2f6df0SHerbert Xu {
2743b2f6df0SHerbert Xu 	struct crypto_alg *calg = tfm->__crt_alg;
2753b2f6df0SHerbert Xu 	struct shash_alg *alg = __crypto_shash_alg(calg);
2763b2f6df0SHerbert Xu 	struct ahash_tfm *crt = &tfm->crt_ahash;
2773b2f6df0SHerbert Xu 	struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
2783b2f6df0SHerbert Xu 	struct crypto_shash *shash;
2793b2f6df0SHerbert Xu 
2803b2f6df0SHerbert Xu 	if (!crypto_mod_get(calg))
2813b2f6df0SHerbert Xu 		return -EAGAIN;
2823b2f6df0SHerbert Xu 
2833f683d61SHerbert Xu 	shash = crypto_create_tfm(calg, &crypto_shash_type);
2843b2f6df0SHerbert Xu 	if (IS_ERR(shash)) {
2853b2f6df0SHerbert Xu 		crypto_mod_put(calg);
2863b2f6df0SHerbert Xu 		return PTR_ERR(shash);
2873b2f6df0SHerbert Xu 	}
2883b2f6df0SHerbert Xu 
2893b2f6df0SHerbert Xu 	*ctx = shash;
2903b2f6df0SHerbert Xu 	tfm->exit = crypto_exit_shash_ops_async;
2913b2f6df0SHerbert Xu 
2923b2f6df0SHerbert Xu 	crt->init = shash_async_init;
2933b2f6df0SHerbert Xu 	crt->update = shash_async_update;
2943b2f6df0SHerbert Xu 	crt->final  = shash_async_final;
2953b2f6df0SHerbert Xu 	crt->digest = shash_async_digest;
2963b2f6df0SHerbert Xu 	crt->setkey = shash_async_setkey;
2973b2f6df0SHerbert Xu 
2983b2f6df0SHerbert Xu 	crt->digestsize = alg->digestsize;
2993b2f6df0SHerbert Xu 	crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash);
3003b2f6df0SHerbert Xu 
3013b2f6df0SHerbert Xu 	return 0;
3023b2f6df0SHerbert Xu }
3033b2f6df0SHerbert Xu 
3045f7082edSHerbert Xu static int shash_compat_setkey(struct crypto_hash *tfm, const u8 *key,
3055f7082edSHerbert Xu 			       unsigned int keylen)
3065f7082edSHerbert Xu {
3075f7082edSHerbert Xu 	struct shash_desc *desc = crypto_hash_ctx(tfm);
3085f7082edSHerbert Xu 
3095f7082edSHerbert Xu 	return crypto_shash_setkey(desc->tfm, key, keylen);
3105f7082edSHerbert Xu }
3115f7082edSHerbert Xu 
3125f7082edSHerbert Xu static int shash_compat_init(struct hash_desc *hdesc)
3135f7082edSHerbert Xu {
3145f7082edSHerbert Xu 	struct shash_desc *desc = crypto_hash_ctx(hdesc->tfm);
3155f7082edSHerbert Xu 
3165f7082edSHerbert Xu 	desc->flags = hdesc->flags;
3175f7082edSHerbert Xu 
3185f7082edSHerbert Xu 	return crypto_shash_init(desc);
3195f7082edSHerbert Xu }
3205f7082edSHerbert Xu 
3215f7082edSHerbert Xu static int shash_compat_update(struct hash_desc *hdesc, struct scatterlist *sg,
3225f7082edSHerbert Xu 			       unsigned int len)
3235f7082edSHerbert Xu {
3245f7082edSHerbert Xu 	struct shash_desc *desc = crypto_hash_ctx(hdesc->tfm);
3255f7082edSHerbert Xu 	struct crypto_hash_walk walk;
3265f7082edSHerbert Xu 	int nbytes;
3275f7082edSHerbert Xu 
3285f7082edSHerbert Xu 	for (nbytes = crypto_hash_walk_first_compat(hdesc, &walk, sg, len);
3295f7082edSHerbert Xu 	     nbytes > 0; nbytes = crypto_hash_walk_done(&walk, nbytes))
3305f7082edSHerbert Xu 		nbytes = crypto_shash_update(desc, walk.data, nbytes);
3315f7082edSHerbert Xu 
3325f7082edSHerbert Xu 	return nbytes;
3335f7082edSHerbert Xu }
3345f7082edSHerbert Xu 
3355f7082edSHerbert Xu static int shash_compat_final(struct hash_desc *hdesc, u8 *out)
3365f7082edSHerbert Xu {
3375f7082edSHerbert Xu 	return crypto_shash_final(crypto_hash_ctx(hdesc->tfm), out);
3385f7082edSHerbert Xu }
3395f7082edSHerbert Xu 
3405f7082edSHerbert Xu static int shash_compat_digest(struct hash_desc *hdesc, struct scatterlist *sg,
3415f7082edSHerbert Xu 			       unsigned int nbytes, u8 *out)
3425f7082edSHerbert Xu {
3435f7082edSHerbert Xu 	unsigned int offset = sg->offset;
3445f7082edSHerbert Xu 	int err;
3455f7082edSHerbert Xu 
3465f7082edSHerbert Xu 	if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) {
3475f7082edSHerbert Xu 		struct shash_desc *desc = crypto_hash_ctx(hdesc->tfm);
3485f7082edSHerbert Xu 		void *data;
3495f7082edSHerbert Xu 
3505f7082edSHerbert Xu 		desc->flags = hdesc->flags;
3515f7082edSHerbert Xu 
3525f7082edSHerbert Xu 		data = crypto_kmap(sg_page(sg), 0);
3535f7082edSHerbert Xu 		err = crypto_shash_digest(desc, data + offset, nbytes, out);
3545f7082edSHerbert Xu 		crypto_kunmap(data, 0);
3555f7082edSHerbert Xu 		crypto_yield(desc->flags);
3565f7082edSHerbert Xu 		goto out;
3575f7082edSHerbert Xu 	}
3585f7082edSHerbert Xu 
3595f7082edSHerbert Xu 	err = shash_compat_init(hdesc);
3605f7082edSHerbert Xu 	if (err)
3615f7082edSHerbert Xu 		goto out;
3625f7082edSHerbert Xu 
3635f7082edSHerbert Xu 	err = shash_compat_update(hdesc, sg, nbytes);
3645f7082edSHerbert Xu 	if (err)
3655f7082edSHerbert Xu 		goto out;
3665f7082edSHerbert Xu 
3675f7082edSHerbert Xu 	err = shash_compat_final(hdesc, out);
3685f7082edSHerbert Xu 
3695f7082edSHerbert Xu out:
3705f7082edSHerbert Xu 	return err;
3715f7082edSHerbert Xu }
3725f7082edSHerbert Xu 
3735f7082edSHerbert Xu static void crypto_exit_shash_ops_compat(struct crypto_tfm *tfm)
3745f7082edSHerbert Xu {
3755f7082edSHerbert Xu 	struct shash_desc *desc= crypto_tfm_ctx(tfm);
3765f7082edSHerbert Xu 
3775f7082edSHerbert Xu 	crypto_free_shash(desc->tfm);
3785f7082edSHerbert Xu }
3795f7082edSHerbert Xu 
3805f7082edSHerbert Xu static int crypto_init_shash_ops_compat(struct crypto_tfm *tfm)
3815f7082edSHerbert Xu {
3825f7082edSHerbert Xu 	struct hash_tfm *crt = &tfm->crt_hash;
3835f7082edSHerbert Xu 	struct crypto_alg *calg = tfm->__crt_alg;
3845f7082edSHerbert Xu 	struct shash_alg *alg = __crypto_shash_alg(calg);
3855f7082edSHerbert Xu 	struct shash_desc *desc = crypto_tfm_ctx(tfm);
3865f7082edSHerbert Xu 	struct crypto_shash *shash;
3875f7082edSHerbert Xu 
3884abfd73eSAdrian-Ken Rueegsegger 	if (!crypto_mod_get(calg))
3894abfd73eSAdrian-Ken Rueegsegger 		return -EAGAIN;
3904abfd73eSAdrian-Ken Rueegsegger 
3913f683d61SHerbert Xu 	shash = crypto_create_tfm(calg, &crypto_shash_type);
3924abfd73eSAdrian-Ken Rueegsegger 	if (IS_ERR(shash)) {
3934abfd73eSAdrian-Ken Rueegsegger 		crypto_mod_put(calg);
3945f7082edSHerbert Xu 		return PTR_ERR(shash);
3954abfd73eSAdrian-Ken Rueegsegger 	}
3965f7082edSHerbert Xu 
3975f7082edSHerbert Xu 	desc->tfm = shash;
3985f7082edSHerbert Xu 	tfm->exit = crypto_exit_shash_ops_compat;
3995f7082edSHerbert Xu 
4005f7082edSHerbert Xu 	crt->init = shash_compat_init;
4015f7082edSHerbert Xu 	crt->update = shash_compat_update;
4025f7082edSHerbert Xu 	crt->final  = shash_compat_final;
4035f7082edSHerbert Xu 	crt->digest = shash_compat_digest;
4045f7082edSHerbert Xu 	crt->setkey = shash_compat_setkey;
4055f7082edSHerbert Xu 
4065f7082edSHerbert Xu 	crt->digestsize = alg->digestsize;
4075f7082edSHerbert Xu 
4085f7082edSHerbert Xu 	return 0;
4095f7082edSHerbert Xu }
4105f7082edSHerbert Xu 
4113b2f6df0SHerbert Xu static int crypto_init_shash_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
4123b2f6df0SHerbert Xu {
4133b2f6df0SHerbert Xu 	switch (mask & CRYPTO_ALG_TYPE_MASK) {
4145f7082edSHerbert Xu 	case CRYPTO_ALG_TYPE_HASH_MASK:
4155f7082edSHerbert Xu 		return crypto_init_shash_ops_compat(tfm);
4163b2f6df0SHerbert Xu 	case CRYPTO_ALG_TYPE_AHASH_MASK:
4173b2f6df0SHerbert Xu 		return crypto_init_shash_ops_async(tfm);
4183b2f6df0SHerbert Xu 	}
4193b2f6df0SHerbert Xu 
4203b2f6df0SHerbert Xu 	return -EINVAL;
4213b2f6df0SHerbert Xu }
4223b2f6df0SHerbert Xu 
4233b2f6df0SHerbert Xu static unsigned int crypto_shash_ctxsize(struct crypto_alg *alg, u32 type,
4243b2f6df0SHerbert Xu 					 u32 mask)
4253b2f6df0SHerbert Xu {
4265f7082edSHerbert Xu 	struct shash_alg *salg = __crypto_shash_alg(alg);
4275f7082edSHerbert Xu 
4283b2f6df0SHerbert Xu 	switch (mask & CRYPTO_ALG_TYPE_MASK) {
4295f7082edSHerbert Xu 	case CRYPTO_ALG_TYPE_HASH_MASK:
4305f7082edSHerbert Xu 		return sizeof(struct shash_desc) + salg->descsize;
4313b2f6df0SHerbert Xu 	case CRYPTO_ALG_TYPE_AHASH_MASK:
4323b2f6df0SHerbert Xu 		return sizeof(struct crypto_shash *);
4333b2f6df0SHerbert Xu 	}
4343b2f6df0SHerbert Xu 
4353b2f6df0SHerbert Xu 	return 0;
4363b2f6df0SHerbert Xu }
4373b2f6df0SHerbert Xu 
4387b5a080bSHerbert Xu static int crypto_shash_init_tfm(struct crypto_tfm *tfm,
4397b5a080bSHerbert Xu 				 const struct crypto_type *frontend)
4407b5a080bSHerbert Xu {
4417b5a080bSHerbert Xu 	return 0;
4427b5a080bSHerbert Xu }
4437b5a080bSHerbert Xu 
4447b5a080bSHerbert Xu static unsigned int crypto_shash_extsize(struct crypto_alg *alg,
4457b5a080bSHerbert Xu 					 const struct crypto_type *frontend)
4467b5a080bSHerbert Xu {
4477b5a080bSHerbert Xu 	return alg->cra_ctxsize;
4487b5a080bSHerbert Xu }
4497b5a080bSHerbert Xu 
4507b5a080bSHerbert Xu static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
4517b5a080bSHerbert Xu 	__attribute__ ((unused));
4527b5a080bSHerbert Xu static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
4537b5a080bSHerbert Xu {
4547b5a080bSHerbert Xu 	struct shash_alg *salg = __crypto_shash_alg(alg);
4557b5a080bSHerbert Xu 
4567b5a080bSHerbert Xu 	seq_printf(m, "type         : shash\n");
4577b5a080bSHerbert Xu 	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
4587b5a080bSHerbert Xu 	seq_printf(m, "digestsize   : %u\n", salg->digestsize);
4597b5a080bSHerbert Xu 	seq_printf(m, "descsize     : %u\n", salg->descsize);
4607b5a080bSHerbert Xu }
4617b5a080bSHerbert Xu 
4627b5a080bSHerbert Xu static const struct crypto_type crypto_shash_type = {
4633b2f6df0SHerbert Xu 	.ctxsize = crypto_shash_ctxsize,
4647b5a080bSHerbert Xu 	.extsize = crypto_shash_extsize,
4653b2f6df0SHerbert Xu 	.init = crypto_init_shash_ops,
4667b5a080bSHerbert Xu 	.init_tfm = crypto_shash_init_tfm,
4677b5a080bSHerbert Xu #ifdef CONFIG_PROC_FS
4687b5a080bSHerbert Xu 	.show = crypto_shash_show,
4697b5a080bSHerbert Xu #endif
4707b5a080bSHerbert Xu 	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
4717b5a080bSHerbert Xu 	.maskset = CRYPTO_ALG_TYPE_MASK,
4727b5a080bSHerbert Xu 	.type = CRYPTO_ALG_TYPE_SHASH,
4737b5a080bSHerbert Xu 	.tfmsize = offsetof(struct crypto_shash, base),
4747b5a080bSHerbert Xu };
4757b5a080bSHerbert Xu 
4767b5a080bSHerbert Xu struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
4777b5a080bSHerbert Xu 					u32 mask)
4787b5a080bSHerbert Xu {
4793f683d61SHerbert Xu 	return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask);
4807b5a080bSHerbert Xu }
4817b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_alloc_shash);
4827b5a080bSHerbert Xu 
483*619a6ebdSHerbert Xu static int shash_prepare_alg(struct shash_alg *alg)
4847b5a080bSHerbert Xu {
4857b5a080bSHerbert Xu 	struct crypto_alg *base = &alg->base;
4867b5a080bSHerbert Xu 
4877b5a080bSHerbert Xu 	if (alg->digestsize > PAGE_SIZE / 8 ||
4887b5a080bSHerbert Xu 	    alg->descsize > PAGE_SIZE / 8)
4897b5a080bSHerbert Xu 		return -EINVAL;
4907b5a080bSHerbert Xu 
4917b5a080bSHerbert Xu 	base->cra_type = &crypto_shash_type;
4927b5a080bSHerbert Xu 	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
4937b5a080bSHerbert Xu 	base->cra_flags |= CRYPTO_ALG_TYPE_SHASH;
494*619a6ebdSHerbert Xu 	return 0;
495*619a6ebdSHerbert Xu }
496*619a6ebdSHerbert Xu 
497*619a6ebdSHerbert Xu int crypto_register_shash(struct shash_alg *alg)
498*619a6ebdSHerbert Xu {
499*619a6ebdSHerbert Xu 	struct crypto_alg *base = &alg->base;
500*619a6ebdSHerbert Xu 	int err;
501*619a6ebdSHerbert Xu 
502*619a6ebdSHerbert Xu 	err = shash_prepare_alg(alg);
503*619a6ebdSHerbert Xu 	if (err)
504*619a6ebdSHerbert Xu 		return err;
5057b5a080bSHerbert Xu 
5067b5a080bSHerbert Xu 	return crypto_register_alg(base);
5077b5a080bSHerbert Xu }
5087b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_register_shash);
5097b5a080bSHerbert Xu 
5107b5a080bSHerbert Xu int crypto_unregister_shash(struct shash_alg *alg)
5117b5a080bSHerbert Xu {
5127b5a080bSHerbert Xu 	return crypto_unregister_alg(&alg->base);
5137b5a080bSHerbert Xu }
5147b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_unregister_shash);
5157b5a080bSHerbert Xu 
516*619a6ebdSHerbert Xu int shash_register_instance(struct crypto_template *tmpl,
517*619a6ebdSHerbert Xu 			    struct shash_instance *inst)
518*619a6ebdSHerbert Xu {
519*619a6ebdSHerbert Xu 	int err;
520*619a6ebdSHerbert Xu 
521*619a6ebdSHerbert Xu 	err = shash_prepare_alg(&inst->alg);
522*619a6ebdSHerbert Xu 	if (err)
523*619a6ebdSHerbert Xu 		return err;
524*619a6ebdSHerbert Xu 
525*619a6ebdSHerbert Xu 	return crypto_register_instance(tmpl, shash_crypto_instance(inst));
526*619a6ebdSHerbert Xu }
527*619a6ebdSHerbert Xu EXPORT_SYMBOL_GPL(shash_register_instance);
528*619a6ebdSHerbert Xu 
5292e4fddd8SHerbert Xu void shash_free_instance(struct crypto_instance *inst)
5302e4fddd8SHerbert Xu {
5312e4fddd8SHerbert Xu 	crypto_drop_spawn(crypto_instance_ctx(inst));
5322e4fddd8SHerbert Xu 	kfree(shash_instance(inst));
5332e4fddd8SHerbert Xu }
5342e4fddd8SHerbert Xu EXPORT_SYMBOL_GPL(shash_free_instance);
5352e4fddd8SHerbert Xu 
53694296999SHerbert Xu int crypto_init_shash_spawn(struct crypto_shash_spawn *spawn,
53794296999SHerbert Xu 			    struct shash_alg *alg,
53894296999SHerbert Xu 			    struct crypto_instance *inst)
53994296999SHerbert Xu {
54094296999SHerbert Xu 	return crypto_init_spawn2(&spawn->base, &alg->base, inst,
54194296999SHerbert Xu 				  &crypto_shash_type);
54294296999SHerbert Xu }
54394296999SHerbert Xu EXPORT_SYMBOL_GPL(crypto_init_shash_spawn);
54494296999SHerbert Xu 
5457d6f5640SHerbert Xu struct shash_alg *shash_attr_alg(struct rtattr *rta, u32 type, u32 mask)
5467d6f5640SHerbert Xu {
5477d6f5640SHerbert Xu 	struct crypto_alg *alg;
5487d6f5640SHerbert Xu 
5497d6f5640SHerbert Xu 	alg = crypto_attr_alg2(rta, &crypto_shash_type, type, mask);
5507d6f5640SHerbert Xu 	return IS_ERR(alg) ? ERR_CAST(alg) :
5517d6f5640SHerbert Xu 	       container_of(alg, struct shash_alg, base);
5527d6f5640SHerbert Xu }
5537d6f5640SHerbert Xu EXPORT_SYMBOL_GPL(shash_attr_alg);
5547d6f5640SHerbert Xu 
5557b5a080bSHerbert Xu MODULE_LICENSE("GPL");
5567b5a080bSHerbert Xu MODULE_DESCRIPTION("Synchronous cryptographic hash type");
557