xref: /linux/crypto/shash.c (revision 01b944fe1cd4e21a2a9ed51adbdbafe2d5e905ba)
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>
20f4d663ceSSteffen Klassert #include <linux/cryptouser.h>
21f4d663ceSSteffen Klassert #include <net/netlink.h>
227b5a080bSHerbert Xu 
233b2f6df0SHerbert Xu #include "internal.h"
243b2f6df0SHerbert Xu 
253f683d61SHerbert Xu static const struct crypto_type crypto_shash_type;
263f683d61SHerbert Xu 
2757cfe44bSHerbert Xu static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
2857cfe44bSHerbert Xu 			   unsigned int keylen)
2957cfe44bSHerbert Xu {
3057cfe44bSHerbert Xu 	return -ENOSYS;
3157cfe44bSHerbert Xu }
3257cfe44bSHerbert Xu 
337b5a080bSHerbert Xu static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
347b5a080bSHerbert Xu 				  unsigned int keylen)
357b5a080bSHerbert Xu {
367b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
377b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
387b5a080bSHerbert Xu 	unsigned long absize;
397b5a080bSHerbert Xu 	u8 *buffer, *alignbuffer;
407b5a080bSHerbert Xu 	int err;
417b5a080bSHerbert Xu 
4218eb8ea6SHerbert Xu 	absize = keylen + (alignmask & ~(crypto_tfm_ctx_alignment() - 1));
437b5a080bSHerbert Xu 	buffer = kmalloc(absize, GFP_KERNEL);
447b5a080bSHerbert Xu 	if (!buffer)
457b5a080bSHerbert Xu 		return -ENOMEM;
467b5a080bSHerbert Xu 
477b5a080bSHerbert Xu 	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
487b5a080bSHerbert Xu 	memcpy(alignbuffer, key, keylen);
497b5a080bSHerbert Xu 	err = shash->setkey(tfm, alignbuffer, keylen);
508c32c516SHerbert Xu 	kzfree(buffer);
517b5a080bSHerbert Xu 	return err;
527b5a080bSHerbert Xu }
537b5a080bSHerbert Xu 
547b5a080bSHerbert Xu int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
557b5a080bSHerbert Xu 			unsigned int keylen)
567b5a080bSHerbert Xu {
577b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
587b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
597b5a080bSHerbert Xu 
607b5a080bSHerbert Xu 	if ((unsigned long)key & alignmask)
617b5a080bSHerbert Xu 		return shash_setkey_unaligned(tfm, key, keylen);
627b5a080bSHerbert Xu 
637b5a080bSHerbert Xu 	return shash->setkey(tfm, key, keylen);
647b5a080bSHerbert Xu }
657b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_setkey);
667b5a080bSHerbert Xu 
677b5a080bSHerbert Xu static inline unsigned int shash_align_buffer_size(unsigned len,
687b5a080bSHerbert Xu 						   unsigned long mask)
697b5a080bSHerbert Xu {
7066d8ea57SMark Charlebois 	typedef u8 __attribute__ ((aligned)) u8_aligned;
7166d8ea57SMark Charlebois 	return len + (mask & ~(__alignof__(u8_aligned) - 1));
727b5a080bSHerbert Xu }
737b5a080bSHerbert Xu 
747b5a080bSHerbert Xu static int shash_update_unaligned(struct shash_desc *desc, const u8 *data,
757b5a080bSHerbert Xu 				  unsigned int len)
767b5a080bSHerbert Xu {
777b5a080bSHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
787b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
797b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
807b5a080bSHerbert Xu 	unsigned int unaligned_len = alignmask + 1 -
817b5a080bSHerbert Xu 				     ((unsigned long)data & alignmask);
820e2d3a12SHerbert Xu 	u8 ubuf[shash_align_buffer_size(unaligned_len, alignmask)]
837b5a080bSHerbert Xu 		__attribute__ ((aligned));
840e2d3a12SHerbert Xu 	u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
858c32c516SHerbert Xu 	int err;
867b5a080bSHerbert Xu 
87f4f68993SYehuda Sadeh 	if (unaligned_len > len)
88f4f68993SYehuda Sadeh 		unaligned_len = len;
89f4f68993SYehuda Sadeh 
907b5a080bSHerbert Xu 	memcpy(buf, data, unaligned_len);
918c32c516SHerbert Xu 	err = shash->update(desc, buf, unaligned_len);
928c32c516SHerbert Xu 	memset(buf, 0, unaligned_len);
937b5a080bSHerbert Xu 
948c32c516SHerbert Xu 	return err ?:
957b5a080bSHerbert Xu 	       shash->update(desc, data + unaligned_len, len - unaligned_len);
967b5a080bSHerbert Xu }
977b5a080bSHerbert Xu 
987b5a080bSHerbert Xu int crypto_shash_update(struct shash_desc *desc, const u8 *data,
997b5a080bSHerbert Xu 			unsigned int len)
1007b5a080bSHerbert Xu {
1017b5a080bSHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
1027b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
1037b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
1047b5a080bSHerbert Xu 
1057b5a080bSHerbert Xu 	if ((unsigned long)data & alignmask)
1067b5a080bSHerbert Xu 		return shash_update_unaligned(desc, data, len);
1077b5a080bSHerbert Xu 
1087b5a080bSHerbert Xu 	return shash->update(desc, data, len);
1097b5a080bSHerbert Xu }
1107b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_update);
1117b5a080bSHerbert Xu 
1127b5a080bSHerbert Xu static int shash_final_unaligned(struct shash_desc *desc, u8 *out)
1137b5a080bSHerbert Xu {
1147b5a080bSHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
1157b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
1167b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
1177b5a080bSHerbert Xu 	unsigned int ds = crypto_shash_digestsize(tfm);
1180e2d3a12SHerbert Xu 	u8 ubuf[shash_align_buffer_size(ds, alignmask)]
1197b5a080bSHerbert Xu 		__attribute__ ((aligned));
1200e2d3a12SHerbert Xu 	u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
1217b5a080bSHerbert Xu 	int err;
1227b5a080bSHerbert Xu 
1237b5a080bSHerbert Xu 	err = shash->final(desc, buf);
1248c32c516SHerbert Xu 	if (err)
1258c32c516SHerbert Xu 		goto out;
1268c32c516SHerbert Xu 
1277b5a080bSHerbert Xu 	memcpy(out, buf, ds);
1288c32c516SHerbert Xu 
1298c32c516SHerbert Xu out:
1308c32c516SHerbert Xu 	memset(buf, 0, ds);
1317b5a080bSHerbert Xu 	return err;
1327b5a080bSHerbert Xu }
1337b5a080bSHerbert Xu 
1347b5a080bSHerbert Xu int crypto_shash_final(struct shash_desc *desc, u8 *out)
1357b5a080bSHerbert Xu {
1367b5a080bSHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
1377b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
1387b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
1397b5a080bSHerbert Xu 
1407b5a080bSHerbert Xu 	if ((unsigned long)out & alignmask)
1417b5a080bSHerbert Xu 		return shash_final_unaligned(desc, out);
1427b5a080bSHerbert Xu 
1437b5a080bSHerbert Xu 	return shash->final(desc, out);
1447b5a080bSHerbert Xu }
1457b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_final);
1467b5a080bSHerbert Xu 
1477b5a080bSHerbert Xu static int shash_finup_unaligned(struct shash_desc *desc, const u8 *data,
1487b5a080bSHerbert Xu 				 unsigned int len, u8 *out)
1497b5a080bSHerbert Xu {
1507b5a080bSHerbert Xu 	return crypto_shash_update(desc, data, len) ?:
1517b5a080bSHerbert Xu 	       crypto_shash_final(desc, out);
1527b5a080bSHerbert Xu }
1537b5a080bSHerbert Xu 
1547b5a080bSHerbert Xu int crypto_shash_finup(struct shash_desc *desc, const u8 *data,
1557b5a080bSHerbert Xu 		       unsigned int len, u8 *out)
1567b5a080bSHerbert Xu {
1577b5a080bSHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
1587b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
1597b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
1607b5a080bSHerbert Xu 
1618267adabSHerbert Xu 	if (((unsigned long)data | (unsigned long)out) & alignmask)
1627b5a080bSHerbert Xu 		return shash_finup_unaligned(desc, data, len, out);
1637b5a080bSHerbert Xu 
1647b5a080bSHerbert Xu 	return shash->finup(desc, data, len, out);
1657b5a080bSHerbert Xu }
1667b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_finup);
1677b5a080bSHerbert Xu 
1687b5a080bSHerbert Xu static int shash_digest_unaligned(struct shash_desc *desc, const u8 *data,
1697b5a080bSHerbert Xu 				  unsigned int len, u8 *out)
1707b5a080bSHerbert Xu {
1717b5a080bSHerbert Xu 	return crypto_shash_init(desc) ?:
172f88ad8deSHerbert Xu 	       crypto_shash_finup(desc, data, len, out);
1737b5a080bSHerbert Xu }
1747b5a080bSHerbert Xu 
1757b5a080bSHerbert Xu int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
1767b5a080bSHerbert Xu 			unsigned int len, u8 *out)
1777b5a080bSHerbert Xu {
1787b5a080bSHerbert Xu 	struct crypto_shash *tfm = desc->tfm;
1797b5a080bSHerbert Xu 	struct shash_alg *shash = crypto_shash_alg(tfm);
1807b5a080bSHerbert Xu 	unsigned long alignmask = crypto_shash_alignmask(tfm);
1817b5a080bSHerbert Xu 
1828267adabSHerbert Xu 	if (((unsigned long)data | (unsigned long)out) & alignmask)
1837b5a080bSHerbert Xu 		return shash_digest_unaligned(desc, data, len, out);
1847b5a080bSHerbert Xu 
1857b5a080bSHerbert Xu 	return shash->digest(desc, data, len, out);
1867b5a080bSHerbert Xu }
1877b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_digest);
1887b5a080bSHerbert Xu 
189f592682fSHerbert Xu static int shash_default_export(struct shash_desc *desc, void *out)
190dec8b786SHerbert Xu {
191f592682fSHerbert Xu 	memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(desc->tfm));
192f592682fSHerbert Xu 	return 0;
193dec8b786SHerbert Xu }
19499d27e1cSHerbert Xu 
195f592682fSHerbert Xu static int shash_default_import(struct shash_desc *desc, const void *in)
19699d27e1cSHerbert Xu {
197f592682fSHerbert Xu 	memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(desc->tfm));
198f592682fSHerbert Xu 	return 0;
19999d27e1cSHerbert Xu }
200dec8b786SHerbert Xu 
2013b2f6df0SHerbert Xu static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
2023b2f6df0SHerbert Xu 			      unsigned int keylen)
2033b2f6df0SHerbert Xu {
2043b2f6df0SHerbert Xu 	struct crypto_shash **ctx = crypto_ahash_ctx(tfm);
2053b2f6df0SHerbert Xu 
2063b2f6df0SHerbert Xu 	return crypto_shash_setkey(*ctx, key, keylen);
2073b2f6df0SHerbert Xu }
2083b2f6df0SHerbert Xu 
2093b2f6df0SHerbert Xu static int shash_async_init(struct ahash_request *req)
2103b2f6df0SHerbert Xu {
2113b2f6df0SHerbert Xu 	struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
2123b2f6df0SHerbert Xu 	struct shash_desc *desc = ahash_request_ctx(req);
2133b2f6df0SHerbert Xu 
2143b2f6df0SHerbert Xu 	desc->tfm = *ctx;
2153b2f6df0SHerbert Xu 	desc->flags = req->base.flags;
2163b2f6df0SHerbert Xu 
2173b2f6df0SHerbert Xu 	return crypto_shash_init(desc);
2183b2f6df0SHerbert Xu }
2193b2f6df0SHerbert Xu 
2207eddf95eSHerbert Xu int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc)
2213b2f6df0SHerbert Xu {
2223b2f6df0SHerbert Xu 	struct crypto_hash_walk walk;
2233b2f6df0SHerbert Xu 	int nbytes;
2243b2f6df0SHerbert Xu 
2253b2f6df0SHerbert Xu 	for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0;
2263b2f6df0SHerbert Xu 	     nbytes = crypto_hash_walk_done(&walk, nbytes))
2273b2f6df0SHerbert Xu 		nbytes = crypto_shash_update(desc, walk.data, nbytes);
2283b2f6df0SHerbert Xu 
2293b2f6df0SHerbert Xu 	return nbytes;
2303b2f6df0SHerbert Xu }
2317eddf95eSHerbert Xu EXPORT_SYMBOL_GPL(shash_ahash_update);
2327eddf95eSHerbert Xu 
2337eddf95eSHerbert Xu static int shash_async_update(struct ahash_request *req)
2347eddf95eSHerbert Xu {
2357eddf95eSHerbert Xu 	return shash_ahash_update(req, ahash_request_ctx(req));
2367eddf95eSHerbert Xu }
2373b2f6df0SHerbert Xu 
2383b2f6df0SHerbert Xu static int shash_async_final(struct ahash_request *req)
2393b2f6df0SHerbert Xu {
2403b2f6df0SHerbert Xu 	return crypto_shash_final(ahash_request_ctx(req), req->result);
2413b2f6df0SHerbert Xu }
2423b2f6df0SHerbert Xu 
24366f6ce5eSHerbert Xu int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc)
24466f6ce5eSHerbert Xu {
24566f6ce5eSHerbert Xu 	struct crypto_hash_walk walk;
24666f6ce5eSHerbert Xu 	int nbytes;
24766f6ce5eSHerbert Xu 
248cbc86b91SHerbert Xu 	nbytes = crypto_hash_walk_first(req, &walk);
249cbc86b91SHerbert Xu 	if (!nbytes)
250cbc86b91SHerbert Xu 		return crypto_shash_final(desc, req->result);
251cbc86b91SHerbert Xu 
252cbc86b91SHerbert Xu 	do {
25366f6ce5eSHerbert Xu 		nbytes = crypto_hash_walk_last(&walk) ?
25466f6ce5eSHerbert Xu 			 crypto_shash_finup(desc, walk.data, nbytes,
25566f6ce5eSHerbert Xu 					    req->result) :
25666f6ce5eSHerbert Xu 			 crypto_shash_update(desc, walk.data, nbytes);
257cbc86b91SHerbert Xu 		nbytes = crypto_hash_walk_done(&walk, nbytes);
258cbc86b91SHerbert Xu 	} while (nbytes > 0);
25966f6ce5eSHerbert Xu 
26066f6ce5eSHerbert Xu 	return nbytes;
26166f6ce5eSHerbert Xu }
26266f6ce5eSHerbert Xu EXPORT_SYMBOL_GPL(shash_ahash_finup);
26366f6ce5eSHerbert Xu 
26466f6ce5eSHerbert Xu static int shash_async_finup(struct ahash_request *req)
26566f6ce5eSHerbert Xu {
26666f6ce5eSHerbert Xu 	struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
26766f6ce5eSHerbert Xu 	struct shash_desc *desc = ahash_request_ctx(req);
26866f6ce5eSHerbert Xu 
26966f6ce5eSHerbert Xu 	desc->tfm = *ctx;
27066f6ce5eSHerbert Xu 	desc->flags = req->base.flags;
27166f6ce5eSHerbert Xu 
27266f6ce5eSHerbert Xu 	return shash_ahash_finup(req, desc);
27366f6ce5eSHerbert Xu }
27466f6ce5eSHerbert Xu 
2757eddf95eSHerbert Xu int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc)
2763b2f6df0SHerbert Xu {
2773b2f6df0SHerbert Xu 	struct scatterlist *sg = req->src;
2783b2f6df0SHerbert Xu 	unsigned int offset = sg->offset;
2793b2f6df0SHerbert Xu 	unsigned int nbytes = req->nbytes;
2803b2f6df0SHerbert Xu 	int err;
2813b2f6df0SHerbert Xu 
2823b2f6df0SHerbert Xu 	if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) {
2833b2f6df0SHerbert Xu 		void *data;
2843b2f6df0SHerbert Xu 
285f0dfc0b0SCong Wang 		data = kmap_atomic(sg_page(sg));
2863b2f6df0SHerbert Xu 		err = crypto_shash_digest(desc, data + offset, nbytes,
2873b2f6df0SHerbert Xu 					  req->result);
288f0dfc0b0SCong Wang 		kunmap_atomic(data);
2893b2f6df0SHerbert Xu 		crypto_yield(desc->flags);
2907eddf95eSHerbert Xu 	} else
2917eddf95eSHerbert Xu 		err = crypto_shash_init(desc) ?:
29266f6ce5eSHerbert Xu 		      shash_ahash_finup(req, desc);
2933b2f6df0SHerbert Xu 
2943b2f6df0SHerbert Xu 	return err;
2953b2f6df0SHerbert Xu }
2967eddf95eSHerbert Xu EXPORT_SYMBOL_GPL(shash_ahash_digest);
2977eddf95eSHerbert Xu 
2987eddf95eSHerbert Xu static int shash_async_digest(struct ahash_request *req)
2997eddf95eSHerbert Xu {
3007eddf95eSHerbert Xu 	struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
3017eddf95eSHerbert Xu 	struct shash_desc *desc = ahash_request_ctx(req);
3027eddf95eSHerbert Xu 
3037eddf95eSHerbert Xu 	desc->tfm = *ctx;
3047eddf95eSHerbert Xu 	desc->flags = req->base.flags;
3057eddf95eSHerbert Xu 
3067eddf95eSHerbert Xu 	return shash_ahash_digest(req, desc);
3077eddf95eSHerbert Xu }
3083b2f6df0SHerbert Xu 
30966f6ce5eSHerbert Xu static int shash_async_export(struct ahash_request *req, void *out)
31066f6ce5eSHerbert Xu {
31166f6ce5eSHerbert Xu 	return crypto_shash_export(ahash_request_ctx(req), out);
31266f6ce5eSHerbert Xu }
31366f6ce5eSHerbert Xu 
31466f6ce5eSHerbert Xu static int shash_async_import(struct ahash_request *req, const void *in)
31566f6ce5eSHerbert Xu {
31690246e79SHerbert Xu 	struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
31790246e79SHerbert Xu 	struct shash_desc *desc = ahash_request_ctx(req);
31890246e79SHerbert Xu 
31990246e79SHerbert Xu 	desc->tfm = *ctx;
32090246e79SHerbert Xu 	desc->flags = req->base.flags;
32190246e79SHerbert Xu 
32290246e79SHerbert Xu 	return crypto_shash_import(desc, in);
32366f6ce5eSHerbert Xu }
32466f6ce5eSHerbert Xu 
3253b2f6df0SHerbert Xu static void crypto_exit_shash_ops_async(struct crypto_tfm *tfm)
3263b2f6df0SHerbert Xu {
3273b2f6df0SHerbert Xu 	struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
3283b2f6df0SHerbert Xu 
3293b2f6df0SHerbert Xu 	crypto_free_shash(*ctx);
3303b2f6df0SHerbert Xu }
3313b2f6df0SHerbert Xu 
33288056ec3SHerbert Xu int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
3333b2f6df0SHerbert Xu {
3343b2f6df0SHerbert Xu 	struct crypto_alg *calg = tfm->__crt_alg;
33566f6ce5eSHerbert Xu 	struct shash_alg *alg = __crypto_shash_alg(calg);
33688056ec3SHerbert Xu 	struct crypto_ahash *crt = __crypto_ahash_cast(tfm);
3373b2f6df0SHerbert Xu 	struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
3383b2f6df0SHerbert Xu 	struct crypto_shash *shash;
3393b2f6df0SHerbert Xu 
3403b2f6df0SHerbert Xu 	if (!crypto_mod_get(calg))
3413b2f6df0SHerbert Xu 		return -EAGAIN;
3423b2f6df0SHerbert Xu 
3433f683d61SHerbert Xu 	shash = crypto_create_tfm(calg, &crypto_shash_type);
3443b2f6df0SHerbert Xu 	if (IS_ERR(shash)) {
3453b2f6df0SHerbert Xu 		crypto_mod_put(calg);
3463b2f6df0SHerbert Xu 		return PTR_ERR(shash);
3473b2f6df0SHerbert Xu 	}
3483b2f6df0SHerbert Xu 
3493b2f6df0SHerbert Xu 	*ctx = shash;
3503b2f6df0SHerbert Xu 	tfm->exit = crypto_exit_shash_ops_async;
3513b2f6df0SHerbert Xu 
3523b2f6df0SHerbert Xu 	crt->init = shash_async_init;
3533b2f6df0SHerbert Xu 	crt->update = shash_async_update;
3543b2f6df0SHerbert Xu 	crt->final = shash_async_final;
35566f6ce5eSHerbert Xu 	crt->finup = shash_async_finup;
3563b2f6df0SHerbert Xu 	crt->digest = shash_async_digest;
35766f6ce5eSHerbert Xu 
35866f6ce5eSHerbert Xu 	if (alg->setkey)
3593b2f6df0SHerbert Xu 		crt->setkey = shash_async_setkey;
36066f6ce5eSHerbert Xu 	if (alg->export)
36166f6ce5eSHerbert Xu 		crt->export = shash_async_export;
3620044f3edSSteffen Klassert 	if (alg->import)
36366f6ce5eSHerbert Xu 		crt->import = shash_async_import;
3643b2f6df0SHerbert Xu 
3653b2f6df0SHerbert Xu 	crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash);
3663b2f6df0SHerbert Xu 
3673b2f6df0SHerbert Xu 	return 0;
3683b2f6df0SHerbert Xu }
3693b2f6df0SHerbert Xu 
3705f7082edSHerbert Xu static int shash_compat_setkey(struct crypto_hash *tfm, const u8 *key,
3715f7082edSHerbert Xu 			       unsigned int keylen)
3725f7082edSHerbert Xu {
373113adefcSHerbert Xu 	struct shash_desc **descp = crypto_hash_ctx(tfm);
374113adefcSHerbert Xu 	struct shash_desc *desc = *descp;
3755f7082edSHerbert Xu 
3765f7082edSHerbert Xu 	return crypto_shash_setkey(desc->tfm, key, keylen);
3775f7082edSHerbert Xu }
3785f7082edSHerbert Xu 
3795f7082edSHerbert Xu static int shash_compat_init(struct hash_desc *hdesc)
3805f7082edSHerbert Xu {
381113adefcSHerbert Xu 	struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm);
382113adefcSHerbert Xu 	struct shash_desc *desc = *descp;
3835f7082edSHerbert Xu 
3845f7082edSHerbert Xu 	desc->flags = hdesc->flags;
3855f7082edSHerbert Xu 
3865f7082edSHerbert Xu 	return crypto_shash_init(desc);
3875f7082edSHerbert Xu }
3885f7082edSHerbert Xu 
3895f7082edSHerbert Xu static int shash_compat_update(struct hash_desc *hdesc, struct scatterlist *sg,
3905f7082edSHerbert Xu 			       unsigned int len)
3915f7082edSHerbert Xu {
392113adefcSHerbert Xu 	struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm);
393113adefcSHerbert Xu 	struct shash_desc *desc = *descp;
3945f7082edSHerbert Xu 	struct crypto_hash_walk walk;
3955f7082edSHerbert Xu 	int nbytes;
3965f7082edSHerbert Xu 
3975f7082edSHerbert Xu 	for (nbytes = crypto_hash_walk_first_compat(hdesc, &walk, sg, len);
3985f7082edSHerbert Xu 	     nbytes > 0; nbytes = crypto_hash_walk_done(&walk, nbytes))
3995f7082edSHerbert Xu 		nbytes = crypto_shash_update(desc, walk.data, nbytes);
4005f7082edSHerbert Xu 
4015f7082edSHerbert Xu 	return nbytes;
4025f7082edSHerbert Xu }
4035f7082edSHerbert Xu 
4045f7082edSHerbert Xu static int shash_compat_final(struct hash_desc *hdesc, u8 *out)
4055f7082edSHerbert Xu {
406113adefcSHerbert Xu 	struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm);
407113adefcSHerbert Xu 
408113adefcSHerbert Xu 	return crypto_shash_final(*descp, out);
4095f7082edSHerbert Xu }
4105f7082edSHerbert Xu 
4115f7082edSHerbert Xu static int shash_compat_digest(struct hash_desc *hdesc, struct scatterlist *sg,
4125f7082edSHerbert Xu 			       unsigned int nbytes, u8 *out)
4135f7082edSHerbert Xu {
4145f7082edSHerbert Xu 	unsigned int offset = sg->offset;
4155f7082edSHerbert Xu 	int err;
4165f7082edSHerbert Xu 
4175f7082edSHerbert Xu 	if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) {
418113adefcSHerbert Xu 		struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm);
419113adefcSHerbert Xu 		struct shash_desc *desc = *descp;
4205f7082edSHerbert Xu 		void *data;
4215f7082edSHerbert Xu 
4225f7082edSHerbert Xu 		desc->flags = hdesc->flags;
4235f7082edSHerbert Xu 
424f0dfc0b0SCong Wang 		data = kmap_atomic(sg_page(sg));
4255f7082edSHerbert Xu 		err = crypto_shash_digest(desc, data + offset, nbytes, out);
426f0dfc0b0SCong Wang 		kunmap_atomic(data);
4275f7082edSHerbert Xu 		crypto_yield(desc->flags);
4285f7082edSHerbert Xu 		goto out;
4295f7082edSHerbert Xu 	}
4305f7082edSHerbert Xu 
4315f7082edSHerbert Xu 	err = shash_compat_init(hdesc);
4325f7082edSHerbert Xu 	if (err)
4335f7082edSHerbert Xu 		goto out;
4345f7082edSHerbert Xu 
4355f7082edSHerbert Xu 	err = shash_compat_update(hdesc, sg, nbytes);
4365f7082edSHerbert Xu 	if (err)
4375f7082edSHerbert Xu 		goto out;
4385f7082edSHerbert Xu 
4395f7082edSHerbert Xu 	err = shash_compat_final(hdesc, out);
4405f7082edSHerbert Xu 
4415f7082edSHerbert Xu out:
4425f7082edSHerbert Xu 	return err;
4435f7082edSHerbert Xu }
4445f7082edSHerbert Xu 
4455f7082edSHerbert Xu static void crypto_exit_shash_ops_compat(struct crypto_tfm *tfm)
4465f7082edSHerbert Xu {
447113adefcSHerbert Xu 	struct shash_desc **descp = crypto_tfm_ctx(tfm);
448113adefcSHerbert Xu 	struct shash_desc *desc = *descp;
4495f7082edSHerbert Xu 
4505f7082edSHerbert Xu 	crypto_free_shash(desc->tfm);
451113adefcSHerbert Xu 	kzfree(desc);
4525f7082edSHerbert Xu }
4535f7082edSHerbert Xu 
4545f7082edSHerbert Xu static int crypto_init_shash_ops_compat(struct crypto_tfm *tfm)
4555f7082edSHerbert Xu {
4565f7082edSHerbert Xu 	struct hash_tfm *crt = &tfm->crt_hash;
4575f7082edSHerbert Xu 	struct crypto_alg *calg = tfm->__crt_alg;
4585f7082edSHerbert Xu 	struct shash_alg *alg = __crypto_shash_alg(calg);
459113adefcSHerbert Xu 	struct shash_desc **descp = crypto_tfm_ctx(tfm);
4605f7082edSHerbert Xu 	struct crypto_shash *shash;
461113adefcSHerbert Xu 	struct shash_desc *desc;
4625f7082edSHerbert Xu 
4634abfd73eSAdrian-Ken Rueegsegger 	if (!crypto_mod_get(calg))
4644abfd73eSAdrian-Ken Rueegsegger 		return -EAGAIN;
4654abfd73eSAdrian-Ken Rueegsegger 
4663f683d61SHerbert Xu 	shash = crypto_create_tfm(calg, &crypto_shash_type);
4674abfd73eSAdrian-Ken Rueegsegger 	if (IS_ERR(shash)) {
4684abfd73eSAdrian-Ken Rueegsegger 		crypto_mod_put(calg);
4695f7082edSHerbert Xu 		return PTR_ERR(shash);
4704abfd73eSAdrian-Ken Rueegsegger 	}
4715f7082edSHerbert Xu 
472113adefcSHerbert Xu 	desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(shash),
473113adefcSHerbert Xu 		       GFP_KERNEL);
474113adefcSHerbert Xu 	if (!desc) {
475113adefcSHerbert Xu 		crypto_free_shash(shash);
476113adefcSHerbert Xu 		return -ENOMEM;
477113adefcSHerbert Xu 	}
478113adefcSHerbert Xu 
479113adefcSHerbert Xu 	*descp = desc;
4805f7082edSHerbert Xu 	desc->tfm = shash;
4815f7082edSHerbert Xu 	tfm->exit = crypto_exit_shash_ops_compat;
4825f7082edSHerbert Xu 
4835f7082edSHerbert Xu 	crt->init = shash_compat_init;
4845f7082edSHerbert Xu 	crt->update = shash_compat_update;
4855f7082edSHerbert Xu 	crt->final  = shash_compat_final;
4865f7082edSHerbert Xu 	crt->digest = shash_compat_digest;
4875f7082edSHerbert Xu 	crt->setkey = shash_compat_setkey;
4885f7082edSHerbert Xu 
4895f7082edSHerbert Xu 	crt->digestsize = alg->digestsize;
4905f7082edSHerbert Xu 
4915f7082edSHerbert Xu 	return 0;
4925f7082edSHerbert Xu }
4935f7082edSHerbert Xu 
4943b2f6df0SHerbert Xu static int crypto_init_shash_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
4953b2f6df0SHerbert Xu {
4963b2f6df0SHerbert Xu 	switch (mask & CRYPTO_ALG_TYPE_MASK) {
4975f7082edSHerbert Xu 	case CRYPTO_ALG_TYPE_HASH_MASK:
4985f7082edSHerbert Xu 		return crypto_init_shash_ops_compat(tfm);
4993b2f6df0SHerbert Xu 	}
5003b2f6df0SHerbert Xu 
5013b2f6df0SHerbert Xu 	return -EINVAL;
5023b2f6df0SHerbert Xu }
5033b2f6df0SHerbert Xu 
5043b2f6df0SHerbert Xu static unsigned int crypto_shash_ctxsize(struct crypto_alg *alg, u32 type,
5053b2f6df0SHerbert Xu 					 u32 mask)
5063b2f6df0SHerbert Xu {
5073b2f6df0SHerbert Xu 	switch (mask & CRYPTO_ALG_TYPE_MASK) {
5085f7082edSHerbert Xu 	case CRYPTO_ALG_TYPE_HASH_MASK:
509113adefcSHerbert Xu 		return sizeof(struct shash_desc *);
5103b2f6df0SHerbert Xu 	}
5113b2f6df0SHerbert Xu 
5123b2f6df0SHerbert Xu 	return 0;
5133b2f6df0SHerbert Xu }
5143b2f6df0SHerbert Xu 
5152ca33da1SHerbert Xu static int crypto_shash_init_tfm(struct crypto_tfm *tfm)
5167b5a080bSHerbert Xu {
517113adefcSHerbert Xu 	struct crypto_shash *hash = __crypto_shash_cast(tfm);
518113adefcSHerbert Xu 
519113adefcSHerbert Xu 	hash->descsize = crypto_shash_alg(hash)->descsize;
5207b5a080bSHerbert Xu 	return 0;
5217b5a080bSHerbert Xu }
5227b5a080bSHerbert Xu 
5233acc8473SHerbert Xu #ifdef CONFIG_NET
524f4d663ceSSteffen Klassert static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
525f4d663ceSSteffen Klassert {
526f4d663ceSSteffen Klassert 	struct crypto_report_hash rhash;
527f4d663ceSSteffen Klassert 	struct shash_alg *salg = __crypto_shash_alg(alg);
528f4d663ceSSteffen Klassert 
5299a5467bfSMathias Krause 	strncpy(rhash.type, "shash", sizeof(rhash.type));
5309a5467bfSMathias Krause 
531f4d663ceSSteffen Klassert 	rhash.blocksize = alg->cra_blocksize;
532f4d663ceSSteffen Klassert 	rhash.digestsize = salg->digestsize;
533f4d663ceSSteffen Klassert 
5346662df33SDavid S. Miller 	if (nla_put(skb, CRYPTOCFGA_REPORT_HASH,
5356662df33SDavid S. Miller 		    sizeof(struct crypto_report_hash), &rhash))
5366662df33SDavid S. Miller 		goto nla_put_failure;
537f4d663ceSSteffen Klassert 	return 0;
538f4d663ceSSteffen Klassert 
539f4d663ceSSteffen Klassert nla_put_failure:
540f4d663ceSSteffen Klassert 	return -EMSGSIZE;
541f4d663ceSSteffen Klassert }
5423acc8473SHerbert Xu #else
5433acc8473SHerbert Xu static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
5443acc8473SHerbert Xu {
5453acc8473SHerbert Xu 	return -ENOSYS;
5463acc8473SHerbert Xu }
5473acc8473SHerbert Xu #endif
548f4d663ceSSteffen Klassert 
5497b5a080bSHerbert Xu static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
5507b5a080bSHerbert Xu 	__attribute__ ((unused));
5517b5a080bSHerbert Xu static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
5527b5a080bSHerbert Xu {
5537b5a080bSHerbert Xu 	struct shash_alg *salg = __crypto_shash_alg(alg);
5547b5a080bSHerbert Xu 
5557b5a080bSHerbert Xu 	seq_printf(m, "type         : shash\n");
5567b5a080bSHerbert Xu 	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
5577b5a080bSHerbert Xu 	seq_printf(m, "digestsize   : %u\n", salg->digestsize);
5587b5a080bSHerbert Xu }
5597b5a080bSHerbert Xu 
5607b5a080bSHerbert Xu static const struct crypto_type crypto_shash_type = {
5613b2f6df0SHerbert Xu 	.ctxsize = crypto_shash_ctxsize,
562ac611680SHerbert Xu 	.extsize = crypto_alg_extsize,
5633b2f6df0SHerbert Xu 	.init = crypto_init_shash_ops,
5647b5a080bSHerbert Xu 	.init_tfm = crypto_shash_init_tfm,
5657b5a080bSHerbert Xu #ifdef CONFIG_PROC_FS
5667b5a080bSHerbert Xu 	.show = crypto_shash_show,
5677b5a080bSHerbert Xu #endif
568f4d663ceSSteffen Klassert 	.report = crypto_shash_report,
5697b5a080bSHerbert Xu 	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
5707b5a080bSHerbert Xu 	.maskset = CRYPTO_ALG_TYPE_MASK,
5717b5a080bSHerbert Xu 	.type = CRYPTO_ALG_TYPE_SHASH,
5727b5a080bSHerbert Xu 	.tfmsize = offsetof(struct crypto_shash, base),
5737b5a080bSHerbert Xu };
5747b5a080bSHerbert Xu 
5757b5a080bSHerbert Xu struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
5767b5a080bSHerbert Xu 					u32 mask)
5777b5a080bSHerbert Xu {
5783f683d61SHerbert Xu 	return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask);
5797b5a080bSHerbert Xu }
5807b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_alloc_shash);
5817b5a080bSHerbert Xu 
582619a6ebdSHerbert Xu static int shash_prepare_alg(struct shash_alg *alg)
5837b5a080bSHerbert Xu {
5847b5a080bSHerbert Xu 	struct crypto_alg *base = &alg->base;
5857b5a080bSHerbert Xu 
5867b5a080bSHerbert Xu 	if (alg->digestsize > PAGE_SIZE / 8 ||
58799d27e1cSHerbert Xu 	    alg->descsize > PAGE_SIZE / 8 ||
58899d27e1cSHerbert Xu 	    alg->statesize > PAGE_SIZE / 8)
5897b5a080bSHerbert Xu 		return -EINVAL;
5907b5a080bSHerbert Xu 
5917b5a080bSHerbert Xu 	base->cra_type = &crypto_shash_type;
5927b5a080bSHerbert Xu 	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
5937b5a080bSHerbert Xu 	base->cra_flags |= CRYPTO_ALG_TYPE_SHASH;
59499d27e1cSHerbert Xu 
5958267adabSHerbert Xu 	if (!alg->finup)
5968267adabSHerbert Xu 		alg->finup = shash_finup_unaligned;
5978267adabSHerbert Xu 	if (!alg->digest)
5988267adabSHerbert Xu 		alg->digest = shash_digest_unaligned;
599f592682fSHerbert Xu 	if (!alg->export) {
600f592682fSHerbert Xu 		alg->export = shash_default_export;
601f592682fSHerbert Xu 		alg->import = shash_default_import;
602f592682fSHerbert Xu 		alg->statesize = alg->descsize;
603f592682fSHerbert Xu 	}
60457cfe44bSHerbert Xu 	if (!alg->setkey)
60557cfe44bSHerbert Xu 		alg->setkey = shash_no_setkey;
60699d27e1cSHerbert Xu 
607619a6ebdSHerbert Xu 	return 0;
608619a6ebdSHerbert Xu }
609619a6ebdSHerbert Xu 
610619a6ebdSHerbert Xu int crypto_register_shash(struct shash_alg *alg)
611619a6ebdSHerbert Xu {
612619a6ebdSHerbert Xu 	struct crypto_alg *base = &alg->base;
613619a6ebdSHerbert Xu 	int err;
614619a6ebdSHerbert Xu 
615619a6ebdSHerbert Xu 	err = shash_prepare_alg(alg);
616619a6ebdSHerbert Xu 	if (err)
617619a6ebdSHerbert Xu 		return err;
6187b5a080bSHerbert Xu 
6197b5a080bSHerbert Xu 	return crypto_register_alg(base);
6207b5a080bSHerbert Xu }
6217b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_register_shash);
6227b5a080bSHerbert Xu 
6237b5a080bSHerbert Xu int crypto_unregister_shash(struct shash_alg *alg)
6247b5a080bSHerbert Xu {
6257b5a080bSHerbert Xu 	return crypto_unregister_alg(&alg->base);
6267b5a080bSHerbert Xu }
6277b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_unregister_shash);
6287b5a080bSHerbert Xu 
62950fc3e8dSJussi Kivilinna int crypto_register_shashes(struct shash_alg *algs, int count)
63050fc3e8dSJussi Kivilinna {
63150fc3e8dSJussi Kivilinna 	int i, ret;
63250fc3e8dSJussi Kivilinna 
63350fc3e8dSJussi Kivilinna 	for (i = 0; i < count; i++) {
63450fc3e8dSJussi Kivilinna 		ret = crypto_register_shash(&algs[i]);
63550fc3e8dSJussi Kivilinna 		if (ret)
63650fc3e8dSJussi Kivilinna 			goto err;
63750fc3e8dSJussi Kivilinna 	}
63850fc3e8dSJussi Kivilinna 
63950fc3e8dSJussi Kivilinna 	return 0;
64050fc3e8dSJussi Kivilinna 
64150fc3e8dSJussi Kivilinna err:
64250fc3e8dSJussi Kivilinna 	for (--i; i >= 0; --i)
64350fc3e8dSJussi Kivilinna 		crypto_unregister_shash(&algs[i]);
64450fc3e8dSJussi Kivilinna 
64550fc3e8dSJussi Kivilinna 	return ret;
64650fc3e8dSJussi Kivilinna }
64750fc3e8dSJussi Kivilinna EXPORT_SYMBOL_GPL(crypto_register_shashes);
64850fc3e8dSJussi Kivilinna 
64950fc3e8dSJussi Kivilinna int crypto_unregister_shashes(struct shash_alg *algs, int count)
65050fc3e8dSJussi Kivilinna {
65150fc3e8dSJussi Kivilinna 	int i, ret;
65250fc3e8dSJussi Kivilinna 
65350fc3e8dSJussi Kivilinna 	for (i = count - 1; i >= 0; --i) {
65450fc3e8dSJussi Kivilinna 		ret = crypto_unregister_shash(&algs[i]);
65550fc3e8dSJussi Kivilinna 		if (ret)
65650fc3e8dSJussi Kivilinna 			pr_err("Failed to unregister %s %s: %d\n",
65750fc3e8dSJussi Kivilinna 			       algs[i].base.cra_driver_name,
65850fc3e8dSJussi Kivilinna 			       algs[i].base.cra_name, ret);
65950fc3e8dSJussi Kivilinna 	}
66050fc3e8dSJussi Kivilinna 
66150fc3e8dSJussi Kivilinna 	return 0;
66250fc3e8dSJussi Kivilinna }
66350fc3e8dSJussi Kivilinna EXPORT_SYMBOL_GPL(crypto_unregister_shashes);
66450fc3e8dSJussi Kivilinna 
665619a6ebdSHerbert Xu int shash_register_instance(struct crypto_template *tmpl,
666619a6ebdSHerbert Xu 			    struct shash_instance *inst)
667619a6ebdSHerbert Xu {
668619a6ebdSHerbert Xu 	int err;
669619a6ebdSHerbert Xu 
670619a6ebdSHerbert Xu 	err = shash_prepare_alg(&inst->alg);
671619a6ebdSHerbert Xu 	if (err)
672619a6ebdSHerbert Xu 		return err;
673619a6ebdSHerbert Xu 
674619a6ebdSHerbert Xu 	return crypto_register_instance(tmpl, shash_crypto_instance(inst));
675619a6ebdSHerbert Xu }
676619a6ebdSHerbert Xu EXPORT_SYMBOL_GPL(shash_register_instance);
677619a6ebdSHerbert Xu 
6782e4fddd8SHerbert Xu void shash_free_instance(struct crypto_instance *inst)
6792e4fddd8SHerbert Xu {
6802e4fddd8SHerbert Xu 	crypto_drop_spawn(crypto_instance_ctx(inst));
6812e4fddd8SHerbert Xu 	kfree(shash_instance(inst));
6822e4fddd8SHerbert Xu }
6832e4fddd8SHerbert Xu EXPORT_SYMBOL_GPL(shash_free_instance);
6842e4fddd8SHerbert Xu 
68594296999SHerbert Xu int crypto_init_shash_spawn(struct crypto_shash_spawn *spawn,
68694296999SHerbert Xu 			    struct shash_alg *alg,
68794296999SHerbert Xu 			    struct crypto_instance *inst)
68894296999SHerbert Xu {
68994296999SHerbert Xu 	return crypto_init_spawn2(&spawn->base, &alg->base, inst,
69094296999SHerbert Xu 				  &crypto_shash_type);
69194296999SHerbert Xu }
69294296999SHerbert Xu EXPORT_SYMBOL_GPL(crypto_init_shash_spawn);
69394296999SHerbert Xu 
6947d6f5640SHerbert Xu struct shash_alg *shash_attr_alg(struct rtattr *rta, u32 type, u32 mask)
6957d6f5640SHerbert Xu {
6967d6f5640SHerbert Xu 	struct crypto_alg *alg;
6977d6f5640SHerbert Xu 
6987d6f5640SHerbert Xu 	alg = crypto_attr_alg2(rta, &crypto_shash_type, type, mask);
6997d6f5640SHerbert Xu 	return IS_ERR(alg) ? ERR_CAST(alg) :
7007d6f5640SHerbert Xu 	       container_of(alg, struct shash_alg, base);
7017d6f5640SHerbert Xu }
7027d6f5640SHerbert Xu EXPORT_SYMBOL_GPL(shash_attr_alg);
7037d6f5640SHerbert Xu 
7047b5a080bSHerbert Xu MODULE_LICENSE("GPL");
7057b5a080bSHerbert Xu MODULE_DESCRIPTION("Synchronous cryptographic hash type");
706