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