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 2557cfe44bSHerbert Xu static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, 2657cfe44bSHerbert Xu unsigned int keylen) 2757cfe44bSHerbert Xu { 2857cfe44bSHerbert Xu return -ENOSYS; 2957cfe44bSHerbert Xu } 3057cfe44bSHerbert Xu 317b5a080bSHerbert Xu static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key, 327b5a080bSHerbert Xu unsigned int keylen) 337b5a080bSHerbert Xu { 347b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 357b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 367b5a080bSHerbert Xu unsigned long absize; 377b5a080bSHerbert Xu u8 *buffer, *alignbuffer; 387b5a080bSHerbert Xu int err; 397b5a080bSHerbert Xu 407b5a080bSHerbert Xu absize = keylen + (alignmask & ~(CRYPTO_MINALIGN - 1)); 417b5a080bSHerbert Xu buffer = kmalloc(absize, GFP_KERNEL); 427b5a080bSHerbert Xu if (!buffer) 437b5a080bSHerbert Xu return -ENOMEM; 447b5a080bSHerbert Xu 457b5a080bSHerbert Xu alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); 467b5a080bSHerbert Xu memcpy(alignbuffer, key, keylen); 477b5a080bSHerbert Xu err = shash->setkey(tfm, alignbuffer, keylen); 488c32c516SHerbert Xu kzfree(buffer); 497b5a080bSHerbert Xu return err; 507b5a080bSHerbert Xu } 517b5a080bSHerbert Xu 527b5a080bSHerbert Xu int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key, 537b5a080bSHerbert Xu unsigned int keylen) 547b5a080bSHerbert Xu { 557b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 567b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 577b5a080bSHerbert Xu 587b5a080bSHerbert Xu if ((unsigned long)key & alignmask) 597b5a080bSHerbert Xu return shash_setkey_unaligned(tfm, key, keylen); 607b5a080bSHerbert Xu 617b5a080bSHerbert Xu return shash->setkey(tfm, key, keylen); 627b5a080bSHerbert Xu } 637b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_setkey); 647b5a080bSHerbert Xu 657b5a080bSHerbert Xu static inline unsigned int shash_align_buffer_size(unsigned len, 667b5a080bSHerbert Xu unsigned long mask) 677b5a080bSHerbert Xu { 687b5a080bSHerbert Xu return len + (mask & ~(__alignof__(u8 __attribute__ ((aligned))) - 1)); 697b5a080bSHerbert Xu } 707b5a080bSHerbert Xu 717b5a080bSHerbert Xu static int shash_update_unaligned(struct shash_desc *desc, const u8 *data, 727b5a080bSHerbert Xu unsigned int len) 737b5a080bSHerbert Xu { 747b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm; 757b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 767b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 777b5a080bSHerbert Xu unsigned int unaligned_len = alignmask + 1 - 787b5a080bSHerbert Xu ((unsigned long)data & alignmask); 790e2d3a12SHerbert Xu u8 ubuf[shash_align_buffer_size(unaligned_len, alignmask)] 807b5a080bSHerbert Xu __attribute__ ((aligned)); 810e2d3a12SHerbert Xu u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1); 828c32c516SHerbert Xu int err; 837b5a080bSHerbert Xu 84f4f68993SYehuda Sadeh if (unaligned_len > len) 85f4f68993SYehuda Sadeh unaligned_len = len; 86f4f68993SYehuda Sadeh 877b5a080bSHerbert Xu memcpy(buf, data, unaligned_len); 888c32c516SHerbert Xu err = shash->update(desc, buf, unaligned_len); 898c32c516SHerbert Xu memset(buf, 0, unaligned_len); 907b5a080bSHerbert Xu 918c32c516SHerbert Xu return err ?: 927b5a080bSHerbert Xu shash->update(desc, data + unaligned_len, len - unaligned_len); 937b5a080bSHerbert Xu } 947b5a080bSHerbert Xu 957b5a080bSHerbert Xu int crypto_shash_update(struct shash_desc *desc, const u8 *data, 967b5a080bSHerbert Xu unsigned int len) 977b5a080bSHerbert Xu { 987b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm; 997b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 1007b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 1017b5a080bSHerbert Xu 1027b5a080bSHerbert Xu if ((unsigned long)data & alignmask) 1037b5a080bSHerbert Xu return shash_update_unaligned(desc, data, len); 1047b5a080bSHerbert Xu 1057b5a080bSHerbert Xu return shash->update(desc, data, len); 1067b5a080bSHerbert Xu } 1077b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_update); 1087b5a080bSHerbert Xu 1097b5a080bSHerbert Xu static int shash_final_unaligned(struct shash_desc *desc, u8 *out) 1107b5a080bSHerbert Xu { 1117b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm; 1127b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 1137b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 1147b5a080bSHerbert Xu unsigned int ds = crypto_shash_digestsize(tfm); 1150e2d3a12SHerbert Xu u8 ubuf[shash_align_buffer_size(ds, alignmask)] 1167b5a080bSHerbert Xu __attribute__ ((aligned)); 1170e2d3a12SHerbert Xu u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1); 1187b5a080bSHerbert Xu int err; 1197b5a080bSHerbert Xu 1207b5a080bSHerbert Xu err = shash->final(desc, buf); 1218c32c516SHerbert Xu if (err) 1228c32c516SHerbert Xu goto out; 1238c32c516SHerbert Xu 1247b5a080bSHerbert Xu memcpy(out, buf, ds); 1258c32c516SHerbert Xu 1268c32c516SHerbert Xu out: 1278c32c516SHerbert Xu memset(buf, 0, ds); 1287b5a080bSHerbert Xu return err; 1297b5a080bSHerbert Xu } 1307b5a080bSHerbert Xu 1317b5a080bSHerbert Xu int crypto_shash_final(struct shash_desc *desc, u8 *out) 1327b5a080bSHerbert Xu { 1337b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm; 1347b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 1357b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 1367b5a080bSHerbert Xu 1377b5a080bSHerbert Xu if ((unsigned long)out & alignmask) 1387b5a080bSHerbert Xu return shash_final_unaligned(desc, out); 1397b5a080bSHerbert Xu 1407b5a080bSHerbert Xu return shash->final(desc, out); 1417b5a080bSHerbert Xu } 1427b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_final); 1437b5a080bSHerbert Xu 1447b5a080bSHerbert Xu static int shash_finup_unaligned(struct shash_desc *desc, const u8 *data, 1457b5a080bSHerbert Xu unsigned int len, u8 *out) 1467b5a080bSHerbert Xu { 1477b5a080bSHerbert Xu return crypto_shash_update(desc, data, len) ?: 1487b5a080bSHerbert Xu crypto_shash_final(desc, out); 1497b5a080bSHerbert Xu } 1507b5a080bSHerbert Xu 1517b5a080bSHerbert Xu int crypto_shash_finup(struct shash_desc *desc, const u8 *data, 1527b5a080bSHerbert Xu unsigned int len, u8 *out) 1537b5a080bSHerbert Xu { 1547b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm; 1557b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 1567b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 1577b5a080bSHerbert Xu 1588267adabSHerbert Xu if (((unsigned long)data | (unsigned long)out) & alignmask) 1597b5a080bSHerbert Xu return shash_finup_unaligned(desc, data, len, out); 1607b5a080bSHerbert Xu 1617b5a080bSHerbert Xu return shash->finup(desc, data, len, out); 1627b5a080bSHerbert Xu } 1637b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_finup); 1647b5a080bSHerbert Xu 1657b5a080bSHerbert Xu static int shash_digest_unaligned(struct shash_desc *desc, const u8 *data, 1667b5a080bSHerbert Xu unsigned int len, u8 *out) 1677b5a080bSHerbert Xu { 1687b5a080bSHerbert Xu return crypto_shash_init(desc) ?: 169f88ad8deSHerbert Xu crypto_shash_finup(desc, data, len, out); 1707b5a080bSHerbert Xu } 1717b5a080bSHerbert Xu 1727b5a080bSHerbert Xu int crypto_shash_digest(struct shash_desc *desc, const u8 *data, 1737b5a080bSHerbert Xu unsigned int len, u8 *out) 1747b5a080bSHerbert Xu { 1757b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm; 1767b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 1777b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 1787b5a080bSHerbert Xu 1798267adabSHerbert Xu if (((unsigned long)data | (unsigned long)out) & alignmask) 1807b5a080bSHerbert Xu return shash_digest_unaligned(desc, data, len, out); 1817b5a080bSHerbert Xu 1827b5a080bSHerbert Xu return shash->digest(desc, data, len, out); 1837b5a080bSHerbert Xu } 1847b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_digest); 1857b5a080bSHerbert Xu 18699d27e1cSHerbert Xu static int shash_no_export(struct shash_desc *desc, void *out) 187dec8b786SHerbert Xu { 18899d27e1cSHerbert Xu return -ENOSYS; 189dec8b786SHerbert Xu } 19099d27e1cSHerbert Xu 19199d27e1cSHerbert Xu static int shash_no_import(struct shash_desc *desc, const void *in) 19299d27e1cSHerbert Xu { 19399d27e1cSHerbert Xu return -ENOSYS; 19499d27e1cSHerbert Xu } 195dec8b786SHerbert Xu 1963b2f6df0SHerbert Xu static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key, 1973b2f6df0SHerbert Xu unsigned int keylen) 1983b2f6df0SHerbert Xu { 1993b2f6df0SHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(tfm); 2003b2f6df0SHerbert Xu 2013b2f6df0SHerbert Xu return crypto_shash_setkey(*ctx, key, keylen); 2023b2f6df0SHerbert Xu } 2033b2f6df0SHerbert Xu 2043b2f6df0SHerbert Xu static int shash_async_init(struct ahash_request *req) 2053b2f6df0SHerbert Xu { 2063b2f6df0SHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 2073b2f6df0SHerbert Xu struct shash_desc *desc = ahash_request_ctx(req); 2083b2f6df0SHerbert Xu 2093b2f6df0SHerbert Xu desc->tfm = *ctx; 2103b2f6df0SHerbert Xu desc->flags = req->base.flags; 2113b2f6df0SHerbert Xu 2123b2f6df0SHerbert Xu return crypto_shash_init(desc); 2133b2f6df0SHerbert Xu } 2143b2f6df0SHerbert Xu 2157eddf95eSHerbert Xu int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc) 2163b2f6df0SHerbert Xu { 2173b2f6df0SHerbert Xu struct crypto_hash_walk walk; 2183b2f6df0SHerbert Xu int nbytes; 2193b2f6df0SHerbert Xu 2203b2f6df0SHerbert Xu for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0; 2213b2f6df0SHerbert Xu nbytes = crypto_hash_walk_done(&walk, nbytes)) 2223b2f6df0SHerbert Xu nbytes = crypto_shash_update(desc, walk.data, nbytes); 2233b2f6df0SHerbert Xu 2243b2f6df0SHerbert Xu return nbytes; 2253b2f6df0SHerbert Xu } 2267eddf95eSHerbert Xu EXPORT_SYMBOL_GPL(shash_ahash_update); 2277eddf95eSHerbert Xu 2287eddf95eSHerbert Xu static int shash_async_update(struct ahash_request *req) 2297eddf95eSHerbert Xu { 2307eddf95eSHerbert Xu return shash_ahash_update(req, ahash_request_ctx(req)); 2317eddf95eSHerbert Xu } 2323b2f6df0SHerbert Xu 2333b2f6df0SHerbert Xu static int shash_async_final(struct ahash_request *req) 2343b2f6df0SHerbert Xu { 2353b2f6df0SHerbert Xu return crypto_shash_final(ahash_request_ctx(req), req->result); 2363b2f6df0SHerbert Xu } 2373b2f6df0SHerbert Xu 238*66f6ce5eSHerbert Xu int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc) 239*66f6ce5eSHerbert Xu { 240*66f6ce5eSHerbert Xu struct crypto_hash_walk walk; 241*66f6ce5eSHerbert Xu int nbytes; 242*66f6ce5eSHerbert Xu 243*66f6ce5eSHerbert Xu for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0; 244*66f6ce5eSHerbert Xu nbytes = crypto_hash_walk_done(&walk, nbytes)) 245*66f6ce5eSHerbert Xu nbytes = crypto_hash_walk_last(&walk) ? 246*66f6ce5eSHerbert Xu crypto_shash_finup(desc, walk.data, nbytes, 247*66f6ce5eSHerbert Xu req->result) : 248*66f6ce5eSHerbert Xu crypto_shash_update(desc, walk.data, nbytes); 249*66f6ce5eSHerbert Xu 250*66f6ce5eSHerbert Xu return nbytes; 251*66f6ce5eSHerbert Xu } 252*66f6ce5eSHerbert Xu EXPORT_SYMBOL_GPL(shash_ahash_finup); 253*66f6ce5eSHerbert Xu 254*66f6ce5eSHerbert Xu static int shash_async_finup(struct ahash_request *req) 255*66f6ce5eSHerbert Xu { 256*66f6ce5eSHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 257*66f6ce5eSHerbert Xu struct shash_desc *desc = ahash_request_ctx(req); 258*66f6ce5eSHerbert Xu 259*66f6ce5eSHerbert Xu desc->tfm = *ctx; 260*66f6ce5eSHerbert Xu desc->flags = req->base.flags; 261*66f6ce5eSHerbert Xu 262*66f6ce5eSHerbert Xu return shash_ahash_finup(req, desc); 263*66f6ce5eSHerbert Xu } 264*66f6ce5eSHerbert Xu 2657eddf95eSHerbert Xu int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc) 2663b2f6df0SHerbert Xu { 2673b2f6df0SHerbert Xu struct scatterlist *sg = req->src; 2683b2f6df0SHerbert Xu unsigned int offset = sg->offset; 2693b2f6df0SHerbert Xu unsigned int nbytes = req->nbytes; 2703b2f6df0SHerbert Xu int err; 2713b2f6df0SHerbert Xu 2723b2f6df0SHerbert Xu if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) { 2733b2f6df0SHerbert Xu void *data; 2743b2f6df0SHerbert Xu 2753b2f6df0SHerbert Xu data = crypto_kmap(sg_page(sg), 0); 2763b2f6df0SHerbert Xu err = crypto_shash_digest(desc, data + offset, nbytes, 2773b2f6df0SHerbert Xu req->result); 2783b2f6df0SHerbert Xu crypto_kunmap(data, 0); 2793b2f6df0SHerbert Xu crypto_yield(desc->flags); 2807eddf95eSHerbert Xu } else 2817eddf95eSHerbert Xu err = crypto_shash_init(desc) ?: 282*66f6ce5eSHerbert Xu shash_ahash_finup(req, desc); 2833b2f6df0SHerbert Xu 2843b2f6df0SHerbert Xu return err; 2853b2f6df0SHerbert Xu } 2867eddf95eSHerbert Xu EXPORT_SYMBOL_GPL(shash_ahash_digest); 2877eddf95eSHerbert Xu 2887eddf95eSHerbert Xu static int shash_async_digest(struct ahash_request *req) 2897eddf95eSHerbert Xu { 2907eddf95eSHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 2917eddf95eSHerbert Xu struct shash_desc *desc = ahash_request_ctx(req); 2927eddf95eSHerbert Xu 2937eddf95eSHerbert Xu desc->tfm = *ctx; 2947eddf95eSHerbert Xu desc->flags = req->base.flags; 2957eddf95eSHerbert Xu 2967eddf95eSHerbert Xu return shash_ahash_digest(req, desc); 2977eddf95eSHerbert Xu } 2983b2f6df0SHerbert Xu 299*66f6ce5eSHerbert Xu static int shash_async_export(struct ahash_request *req, void *out) 300*66f6ce5eSHerbert Xu { 301*66f6ce5eSHerbert Xu return crypto_shash_export(ahash_request_ctx(req), out); 302*66f6ce5eSHerbert Xu } 303*66f6ce5eSHerbert Xu 304*66f6ce5eSHerbert Xu static int shash_async_import(struct ahash_request *req, const void *in) 305*66f6ce5eSHerbert Xu { 306*66f6ce5eSHerbert Xu return crypto_shash_import(ahash_request_ctx(req), in); 307*66f6ce5eSHerbert Xu } 308*66f6ce5eSHerbert Xu 3093b2f6df0SHerbert Xu static void crypto_exit_shash_ops_async(struct crypto_tfm *tfm) 3103b2f6df0SHerbert Xu { 3113b2f6df0SHerbert Xu struct crypto_shash **ctx = crypto_tfm_ctx(tfm); 3123b2f6df0SHerbert Xu 3133b2f6df0SHerbert Xu crypto_free_shash(*ctx); 3143b2f6df0SHerbert Xu } 3153b2f6df0SHerbert Xu 31688056ec3SHerbert Xu int crypto_init_shash_ops_async(struct crypto_tfm *tfm) 3173b2f6df0SHerbert Xu { 3183b2f6df0SHerbert Xu struct crypto_alg *calg = tfm->__crt_alg; 319*66f6ce5eSHerbert Xu struct shash_alg *alg = __crypto_shash_alg(calg); 32088056ec3SHerbert Xu struct crypto_ahash *crt = __crypto_ahash_cast(tfm); 3213b2f6df0SHerbert Xu struct crypto_shash **ctx = crypto_tfm_ctx(tfm); 3223b2f6df0SHerbert Xu struct crypto_shash *shash; 3233b2f6df0SHerbert Xu 3243b2f6df0SHerbert Xu if (!crypto_mod_get(calg)) 3253b2f6df0SHerbert Xu return -EAGAIN; 3263b2f6df0SHerbert Xu 3273f683d61SHerbert Xu shash = crypto_create_tfm(calg, &crypto_shash_type); 3283b2f6df0SHerbert Xu if (IS_ERR(shash)) { 3293b2f6df0SHerbert Xu crypto_mod_put(calg); 3303b2f6df0SHerbert Xu return PTR_ERR(shash); 3313b2f6df0SHerbert Xu } 3323b2f6df0SHerbert Xu 3333b2f6df0SHerbert Xu *ctx = shash; 3343b2f6df0SHerbert Xu tfm->exit = crypto_exit_shash_ops_async; 3353b2f6df0SHerbert Xu 3363b2f6df0SHerbert Xu crt->init = shash_async_init; 3373b2f6df0SHerbert Xu crt->update = shash_async_update; 3383b2f6df0SHerbert Xu crt->final = shash_async_final; 339*66f6ce5eSHerbert Xu crt->finup = shash_async_finup; 3403b2f6df0SHerbert Xu crt->digest = shash_async_digest; 341*66f6ce5eSHerbert Xu 342*66f6ce5eSHerbert Xu if (alg->setkey) 3433b2f6df0SHerbert Xu crt->setkey = shash_async_setkey; 344*66f6ce5eSHerbert Xu if (alg->export) 345*66f6ce5eSHerbert Xu crt->export = shash_async_export; 346*66f6ce5eSHerbert Xu if (alg->setkey) 347*66f6ce5eSHerbert Xu crt->import = shash_async_import; 3483b2f6df0SHerbert Xu 3493b2f6df0SHerbert Xu crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash); 3503b2f6df0SHerbert Xu 3513b2f6df0SHerbert Xu return 0; 3523b2f6df0SHerbert Xu } 3533b2f6df0SHerbert Xu 3545f7082edSHerbert Xu static int shash_compat_setkey(struct crypto_hash *tfm, const u8 *key, 3555f7082edSHerbert Xu unsigned int keylen) 3565f7082edSHerbert Xu { 357113adefcSHerbert Xu struct shash_desc **descp = crypto_hash_ctx(tfm); 358113adefcSHerbert Xu struct shash_desc *desc = *descp; 3595f7082edSHerbert Xu 3605f7082edSHerbert Xu return crypto_shash_setkey(desc->tfm, key, keylen); 3615f7082edSHerbert Xu } 3625f7082edSHerbert Xu 3635f7082edSHerbert Xu static int shash_compat_init(struct hash_desc *hdesc) 3645f7082edSHerbert Xu { 365113adefcSHerbert Xu struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm); 366113adefcSHerbert Xu struct shash_desc *desc = *descp; 3675f7082edSHerbert Xu 3685f7082edSHerbert Xu desc->flags = hdesc->flags; 3695f7082edSHerbert Xu 3705f7082edSHerbert Xu return crypto_shash_init(desc); 3715f7082edSHerbert Xu } 3725f7082edSHerbert Xu 3735f7082edSHerbert Xu static int shash_compat_update(struct hash_desc *hdesc, struct scatterlist *sg, 3745f7082edSHerbert Xu unsigned int len) 3755f7082edSHerbert Xu { 376113adefcSHerbert Xu struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm); 377113adefcSHerbert Xu struct shash_desc *desc = *descp; 3785f7082edSHerbert Xu struct crypto_hash_walk walk; 3795f7082edSHerbert Xu int nbytes; 3805f7082edSHerbert Xu 3815f7082edSHerbert Xu for (nbytes = crypto_hash_walk_first_compat(hdesc, &walk, sg, len); 3825f7082edSHerbert Xu nbytes > 0; nbytes = crypto_hash_walk_done(&walk, nbytes)) 3835f7082edSHerbert Xu nbytes = crypto_shash_update(desc, walk.data, nbytes); 3845f7082edSHerbert Xu 3855f7082edSHerbert Xu return nbytes; 3865f7082edSHerbert Xu } 3875f7082edSHerbert Xu 3885f7082edSHerbert Xu static int shash_compat_final(struct hash_desc *hdesc, u8 *out) 3895f7082edSHerbert Xu { 390113adefcSHerbert Xu struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm); 391113adefcSHerbert Xu 392113adefcSHerbert Xu return crypto_shash_final(*descp, out); 3935f7082edSHerbert Xu } 3945f7082edSHerbert Xu 3955f7082edSHerbert Xu static int shash_compat_digest(struct hash_desc *hdesc, struct scatterlist *sg, 3965f7082edSHerbert Xu unsigned int nbytes, u8 *out) 3975f7082edSHerbert Xu { 3985f7082edSHerbert Xu unsigned int offset = sg->offset; 3995f7082edSHerbert Xu int err; 4005f7082edSHerbert Xu 4015f7082edSHerbert Xu if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) { 402113adefcSHerbert Xu struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm); 403113adefcSHerbert Xu struct shash_desc *desc = *descp; 4045f7082edSHerbert Xu void *data; 4055f7082edSHerbert Xu 4065f7082edSHerbert Xu desc->flags = hdesc->flags; 4075f7082edSHerbert Xu 4085f7082edSHerbert Xu data = crypto_kmap(sg_page(sg), 0); 4095f7082edSHerbert Xu err = crypto_shash_digest(desc, data + offset, nbytes, out); 4105f7082edSHerbert Xu crypto_kunmap(data, 0); 4115f7082edSHerbert Xu crypto_yield(desc->flags); 4125f7082edSHerbert Xu goto out; 4135f7082edSHerbert Xu } 4145f7082edSHerbert Xu 4155f7082edSHerbert Xu err = shash_compat_init(hdesc); 4165f7082edSHerbert Xu if (err) 4175f7082edSHerbert Xu goto out; 4185f7082edSHerbert Xu 4195f7082edSHerbert Xu err = shash_compat_update(hdesc, sg, nbytes); 4205f7082edSHerbert Xu if (err) 4215f7082edSHerbert Xu goto out; 4225f7082edSHerbert Xu 4235f7082edSHerbert Xu err = shash_compat_final(hdesc, out); 4245f7082edSHerbert Xu 4255f7082edSHerbert Xu out: 4265f7082edSHerbert Xu return err; 4275f7082edSHerbert Xu } 4285f7082edSHerbert Xu 4295f7082edSHerbert Xu static void crypto_exit_shash_ops_compat(struct crypto_tfm *tfm) 4305f7082edSHerbert Xu { 431113adefcSHerbert Xu struct shash_desc **descp = crypto_tfm_ctx(tfm); 432113adefcSHerbert Xu struct shash_desc *desc = *descp; 4335f7082edSHerbert Xu 4345f7082edSHerbert Xu crypto_free_shash(desc->tfm); 435113adefcSHerbert Xu kzfree(desc); 4365f7082edSHerbert Xu } 4375f7082edSHerbert Xu 4385f7082edSHerbert Xu static int crypto_init_shash_ops_compat(struct crypto_tfm *tfm) 4395f7082edSHerbert Xu { 4405f7082edSHerbert Xu struct hash_tfm *crt = &tfm->crt_hash; 4415f7082edSHerbert Xu struct crypto_alg *calg = tfm->__crt_alg; 4425f7082edSHerbert Xu struct shash_alg *alg = __crypto_shash_alg(calg); 443113adefcSHerbert Xu struct shash_desc **descp = crypto_tfm_ctx(tfm); 4445f7082edSHerbert Xu struct crypto_shash *shash; 445113adefcSHerbert Xu struct shash_desc *desc; 4465f7082edSHerbert Xu 4474abfd73eSAdrian-Ken Rueegsegger if (!crypto_mod_get(calg)) 4484abfd73eSAdrian-Ken Rueegsegger return -EAGAIN; 4494abfd73eSAdrian-Ken Rueegsegger 4503f683d61SHerbert Xu shash = crypto_create_tfm(calg, &crypto_shash_type); 4514abfd73eSAdrian-Ken Rueegsegger if (IS_ERR(shash)) { 4524abfd73eSAdrian-Ken Rueegsegger crypto_mod_put(calg); 4535f7082edSHerbert Xu return PTR_ERR(shash); 4544abfd73eSAdrian-Ken Rueegsegger } 4555f7082edSHerbert Xu 456113adefcSHerbert Xu desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(shash), 457113adefcSHerbert Xu GFP_KERNEL); 458113adefcSHerbert Xu if (!desc) { 459113adefcSHerbert Xu crypto_free_shash(shash); 460113adefcSHerbert Xu return -ENOMEM; 461113adefcSHerbert Xu } 462113adefcSHerbert Xu 463113adefcSHerbert Xu *descp = desc; 4645f7082edSHerbert Xu desc->tfm = shash; 4655f7082edSHerbert Xu tfm->exit = crypto_exit_shash_ops_compat; 4665f7082edSHerbert Xu 4675f7082edSHerbert Xu crt->init = shash_compat_init; 4685f7082edSHerbert Xu crt->update = shash_compat_update; 4695f7082edSHerbert Xu crt->final = shash_compat_final; 4705f7082edSHerbert Xu crt->digest = shash_compat_digest; 4715f7082edSHerbert Xu crt->setkey = shash_compat_setkey; 4725f7082edSHerbert Xu 4735f7082edSHerbert Xu crt->digestsize = alg->digestsize; 4745f7082edSHerbert Xu 4755f7082edSHerbert Xu return 0; 4765f7082edSHerbert Xu } 4775f7082edSHerbert Xu 4783b2f6df0SHerbert Xu static int crypto_init_shash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) 4793b2f6df0SHerbert Xu { 4803b2f6df0SHerbert Xu switch (mask & CRYPTO_ALG_TYPE_MASK) { 4815f7082edSHerbert Xu case CRYPTO_ALG_TYPE_HASH_MASK: 4825f7082edSHerbert Xu return crypto_init_shash_ops_compat(tfm); 4833b2f6df0SHerbert Xu } 4843b2f6df0SHerbert Xu 4853b2f6df0SHerbert Xu return -EINVAL; 4863b2f6df0SHerbert Xu } 4873b2f6df0SHerbert Xu 4883b2f6df0SHerbert Xu static unsigned int crypto_shash_ctxsize(struct crypto_alg *alg, u32 type, 4893b2f6df0SHerbert Xu u32 mask) 4903b2f6df0SHerbert Xu { 4913b2f6df0SHerbert Xu switch (mask & CRYPTO_ALG_TYPE_MASK) { 4925f7082edSHerbert Xu case CRYPTO_ALG_TYPE_HASH_MASK: 493113adefcSHerbert Xu return sizeof(struct shash_desc *); 4943b2f6df0SHerbert Xu } 4953b2f6df0SHerbert Xu 4963b2f6df0SHerbert Xu return 0; 4973b2f6df0SHerbert Xu } 4983b2f6df0SHerbert Xu 4992ca33da1SHerbert Xu static int crypto_shash_init_tfm(struct crypto_tfm *tfm) 5007b5a080bSHerbert Xu { 501113adefcSHerbert Xu struct crypto_shash *hash = __crypto_shash_cast(tfm); 502113adefcSHerbert Xu 503113adefcSHerbert Xu hash->descsize = crypto_shash_alg(hash)->descsize; 5047b5a080bSHerbert Xu return 0; 5057b5a080bSHerbert Xu } 5067b5a080bSHerbert Xu 5072ca33da1SHerbert Xu static unsigned int crypto_shash_extsize(struct crypto_alg *alg) 5087b5a080bSHerbert Xu { 5097b5a080bSHerbert Xu return alg->cra_ctxsize; 5107b5a080bSHerbert Xu } 5117b5a080bSHerbert Xu 5127b5a080bSHerbert Xu static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg) 5137b5a080bSHerbert Xu __attribute__ ((unused)); 5147b5a080bSHerbert Xu static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg) 5157b5a080bSHerbert Xu { 5167b5a080bSHerbert Xu struct shash_alg *salg = __crypto_shash_alg(alg); 5177b5a080bSHerbert Xu 5187b5a080bSHerbert Xu seq_printf(m, "type : shash\n"); 5197b5a080bSHerbert Xu seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); 5207b5a080bSHerbert Xu seq_printf(m, "digestsize : %u\n", salg->digestsize); 5217b5a080bSHerbert Xu } 5227b5a080bSHerbert Xu 5237b5a080bSHerbert Xu static const struct crypto_type crypto_shash_type = { 5243b2f6df0SHerbert Xu .ctxsize = crypto_shash_ctxsize, 5257b5a080bSHerbert Xu .extsize = crypto_shash_extsize, 5263b2f6df0SHerbert Xu .init = crypto_init_shash_ops, 5277b5a080bSHerbert Xu .init_tfm = crypto_shash_init_tfm, 5287b5a080bSHerbert Xu #ifdef CONFIG_PROC_FS 5297b5a080bSHerbert Xu .show = crypto_shash_show, 5307b5a080bSHerbert Xu #endif 5317b5a080bSHerbert Xu .maskclear = ~CRYPTO_ALG_TYPE_MASK, 5327b5a080bSHerbert Xu .maskset = CRYPTO_ALG_TYPE_MASK, 5337b5a080bSHerbert Xu .type = CRYPTO_ALG_TYPE_SHASH, 5347b5a080bSHerbert Xu .tfmsize = offsetof(struct crypto_shash, base), 5357b5a080bSHerbert Xu }; 5367b5a080bSHerbert Xu 5377b5a080bSHerbert Xu struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type, 5387b5a080bSHerbert Xu u32 mask) 5397b5a080bSHerbert Xu { 5403f683d61SHerbert Xu return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask); 5417b5a080bSHerbert Xu } 5427b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_alloc_shash); 5437b5a080bSHerbert Xu 544619a6ebdSHerbert Xu static int shash_prepare_alg(struct shash_alg *alg) 5457b5a080bSHerbert Xu { 5467b5a080bSHerbert Xu struct crypto_alg *base = &alg->base; 5477b5a080bSHerbert Xu 5487b5a080bSHerbert Xu if (alg->digestsize > PAGE_SIZE / 8 || 54999d27e1cSHerbert Xu alg->descsize > PAGE_SIZE / 8 || 55099d27e1cSHerbert Xu alg->statesize > PAGE_SIZE / 8) 5517b5a080bSHerbert Xu return -EINVAL; 5527b5a080bSHerbert Xu 5537b5a080bSHerbert Xu base->cra_type = &crypto_shash_type; 5547b5a080bSHerbert Xu base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; 5557b5a080bSHerbert Xu base->cra_flags |= CRYPTO_ALG_TYPE_SHASH; 55699d27e1cSHerbert Xu 5578267adabSHerbert Xu if (!alg->finup) 5588267adabSHerbert Xu alg->finup = shash_finup_unaligned; 5598267adabSHerbert Xu if (!alg->digest) 5608267adabSHerbert Xu alg->digest = shash_digest_unaligned; 56199d27e1cSHerbert Xu if (!alg->import) 56299d27e1cSHerbert Xu alg->import = shash_no_import; 56399d27e1cSHerbert Xu if (!alg->export) 56499d27e1cSHerbert Xu alg->export = shash_no_export; 56557cfe44bSHerbert Xu if (!alg->setkey) 56657cfe44bSHerbert Xu alg->setkey = shash_no_setkey; 56799d27e1cSHerbert Xu 568619a6ebdSHerbert Xu return 0; 569619a6ebdSHerbert Xu } 570619a6ebdSHerbert Xu 571619a6ebdSHerbert Xu int crypto_register_shash(struct shash_alg *alg) 572619a6ebdSHerbert Xu { 573619a6ebdSHerbert Xu struct crypto_alg *base = &alg->base; 574619a6ebdSHerbert Xu int err; 575619a6ebdSHerbert Xu 576619a6ebdSHerbert Xu err = shash_prepare_alg(alg); 577619a6ebdSHerbert Xu if (err) 578619a6ebdSHerbert Xu return err; 5797b5a080bSHerbert Xu 5807b5a080bSHerbert Xu return crypto_register_alg(base); 5817b5a080bSHerbert Xu } 5827b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_register_shash); 5837b5a080bSHerbert Xu 5847b5a080bSHerbert Xu int crypto_unregister_shash(struct shash_alg *alg) 5857b5a080bSHerbert Xu { 5867b5a080bSHerbert Xu return crypto_unregister_alg(&alg->base); 5877b5a080bSHerbert Xu } 5887b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_unregister_shash); 5897b5a080bSHerbert Xu 590619a6ebdSHerbert Xu int shash_register_instance(struct crypto_template *tmpl, 591619a6ebdSHerbert Xu struct shash_instance *inst) 592619a6ebdSHerbert Xu { 593619a6ebdSHerbert Xu int err; 594619a6ebdSHerbert Xu 595619a6ebdSHerbert Xu err = shash_prepare_alg(&inst->alg); 596619a6ebdSHerbert Xu if (err) 597619a6ebdSHerbert Xu return err; 598619a6ebdSHerbert Xu 599619a6ebdSHerbert Xu return crypto_register_instance(tmpl, shash_crypto_instance(inst)); 600619a6ebdSHerbert Xu } 601619a6ebdSHerbert Xu EXPORT_SYMBOL_GPL(shash_register_instance); 602619a6ebdSHerbert Xu 6032e4fddd8SHerbert Xu void shash_free_instance(struct crypto_instance *inst) 6042e4fddd8SHerbert Xu { 6052e4fddd8SHerbert Xu crypto_drop_spawn(crypto_instance_ctx(inst)); 6062e4fddd8SHerbert Xu kfree(shash_instance(inst)); 6072e4fddd8SHerbert Xu } 6082e4fddd8SHerbert Xu EXPORT_SYMBOL_GPL(shash_free_instance); 6092e4fddd8SHerbert Xu 61094296999SHerbert Xu int crypto_init_shash_spawn(struct crypto_shash_spawn *spawn, 61194296999SHerbert Xu struct shash_alg *alg, 61294296999SHerbert Xu struct crypto_instance *inst) 61394296999SHerbert Xu { 61494296999SHerbert Xu return crypto_init_spawn2(&spawn->base, &alg->base, inst, 61594296999SHerbert Xu &crypto_shash_type); 61694296999SHerbert Xu } 61794296999SHerbert Xu EXPORT_SYMBOL_GPL(crypto_init_shash_spawn); 61894296999SHerbert Xu 6197d6f5640SHerbert Xu struct shash_alg *shash_attr_alg(struct rtattr *rta, u32 type, u32 mask) 6207d6f5640SHerbert Xu { 6217d6f5640SHerbert Xu struct crypto_alg *alg; 6227d6f5640SHerbert Xu 6237d6f5640SHerbert Xu alg = crypto_attr_alg2(rta, &crypto_shash_type, type, mask); 6247d6f5640SHerbert Xu return IS_ERR(alg) ? ERR_CAST(alg) : 6257d6f5640SHerbert Xu container_of(alg, struct shash_alg, base); 6267d6f5640SHerbert Xu } 6277d6f5640SHerbert Xu EXPORT_SYMBOL_GPL(shash_attr_alg); 6287d6f5640SHerbert Xu 6297b5a080bSHerbert Xu MODULE_LICENSE("GPL"); 6307b5a080bSHerbert Xu MODULE_DESCRIPTION("Synchronous cryptographic hash type"); 631