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); 487b5a080bSHerbert Xu memset(alignbuffer, 0, keylen); 497b5a080bSHerbert Xu kfree(buffer); 507b5a080bSHerbert Xu return err; 517b5a080bSHerbert Xu } 527b5a080bSHerbert Xu 537b5a080bSHerbert Xu int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key, 547b5a080bSHerbert Xu unsigned int keylen) 557b5a080bSHerbert Xu { 567b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 577b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 587b5a080bSHerbert Xu 597b5a080bSHerbert Xu if ((unsigned long)key & alignmask) 607b5a080bSHerbert Xu return shash_setkey_unaligned(tfm, key, keylen); 617b5a080bSHerbert Xu 627b5a080bSHerbert Xu return shash->setkey(tfm, key, keylen); 637b5a080bSHerbert Xu } 647b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_setkey); 657b5a080bSHerbert Xu 667b5a080bSHerbert Xu static inline unsigned int shash_align_buffer_size(unsigned len, 677b5a080bSHerbert Xu unsigned long mask) 687b5a080bSHerbert Xu { 697b5a080bSHerbert Xu return len + (mask & ~(__alignof__(u8 __attribute__ ((aligned))) - 1)); 707b5a080bSHerbert Xu } 717b5a080bSHerbert Xu 727b5a080bSHerbert Xu static int shash_update_unaligned(struct shash_desc *desc, const u8 *data, 737b5a080bSHerbert Xu unsigned int len) 747b5a080bSHerbert Xu { 757b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm; 767b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 777b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 787b5a080bSHerbert Xu unsigned int unaligned_len = alignmask + 1 - 797b5a080bSHerbert Xu ((unsigned long)data & alignmask); 807b5a080bSHerbert Xu u8 buf[shash_align_buffer_size(unaligned_len, alignmask)] 817b5a080bSHerbert Xu __attribute__ ((aligned)); 827b5a080bSHerbert Xu 83f4f68993SYehuda Sadeh if (unaligned_len > len) 84f4f68993SYehuda Sadeh unaligned_len = len; 85f4f68993SYehuda Sadeh 867b5a080bSHerbert Xu memcpy(buf, data, unaligned_len); 877b5a080bSHerbert Xu 887b5a080bSHerbert Xu return shash->update(desc, buf, unaligned_len) ?: 897b5a080bSHerbert Xu shash->update(desc, data + unaligned_len, len - unaligned_len); 907b5a080bSHerbert Xu } 917b5a080bSHerbert Xu 927b5a080bSHerbert Xu int crypto_shash_update(struct shash_desc *desc, const u8 *data, 937b5a080bSHerbert Xu unsigned int len) 947b5a080bSHerbert Xu { 957b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm; 967b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 977b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 987b5a080bSHerbert Xu 997b5a080bSHerbert Xu if ((unsigned long)data & alignmask) 1007b5a080bSHerbert Xu return shash_update_unaligned(desc, data, len); 1017b5a080bSHerbert Xu 1027b5a080bSHerbert Xu return shash->update(desc, data, len); 1037b5a080bSHerbert Xu } 1047b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_update); 1057b5a080bSHerbert Xu 1067b5a080bSHerbert Xu static int shash_final_unaligned(struct shash_desc *desc, u8 *out) 1077b5a080bSHerbert Xu { 1087b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm; 1097b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 1107b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 1117b5a080bSHerbert Xu unsigned int ds = crypto_shash_digestsize(tfm); 1127b5a080bSHerbert Xu u8 buf[shash_align_buffer_size(ds, alignmask)] 1137b5a080bSHerbert Xu __attribute__ ((aligned)); 1147b5a080bSHerbert Xu int err; 1157b5a080bSHerbert Xu 1167b5a080bSHerbert Xu err = shash->final(desc, buf); 1177b5a080bSHerbert Xu memcpy(out, buf, ds); 1187b5a080bSHerbert Xu return err; 1197b5a080bSHerbert Xu } 1207b5a080bSHerbert Xu 1217b5a080bSHerbert Xu int crypto_shash_final(struct shash_desc *desc, u8 *out) 1227b5a080bSHerbert Xu { 1237b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm; 1247b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 1257b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 1267b5a080bSHerbert Xu 1277b5a080bSHerbert Xu if ((unsigned long)out & alignmask) 1287b5a080bSHerbert Xu return shash_final_unaligned(desc, out); 1297b5a080bSHerbert Xu 1307b5a080bSHerbert Xu return shash->final(desc, out); 1317b5a080bSHerbert Xu } 1327b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_final); 1337b5a080bSHerbert Xu 1347b5a080bSHerbert Xu static int shash_finup_unaligned(struct shash_desc *desc, const u8 *data, 1357b5a080bSHerbert Xu unsigned int len, u8 *out) 1367b5a080bSHerbert Xu { 1377b5a080bSHerbert Xu return crypto_shash_update(desc, data, len) ?: 1387b5a080bSHerbert Xu crypto_shash_final(desc, out); 1397b5a080bSHerbert Xu } 1407b5a080bSHerbert Xu 1417b5a080bSHerbert Xu int crypto_shash_finup(struct shash_desc *desc, const u8 *data, 1427b5a080bSHerbert Xu unsigned int len, u8 *out) 1437b5a080bSHerbert Xu { 1447b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm; 1457b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 1467b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 1477b5a080bSHerbert Xu 1488267adabSHerbert Xu if (((unsigned long)data | (unsigned long)out) & alignmask) 1497b5a080bSHerbert Xu return shash_finup_unaligned(desc, data, len, out); 1507b5a080bSHerbert Xu 1517b5a080bSHerbert Xu return shash->finup(desc, data, len, out); 1527b5a080bSHerbert Xu } 1537b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_finup); 1547b5a080bSHerbert Xu 1557b5a080bSHerbert Xu static int shash_digest_unaligned(struct shash_desc *desc, const u8 *data, 1567b5a080bSHerbert Xu unsigned int len, u8 *out) 1577b5a080bSHerbert Xu { 1587b5a080bSHerbert Xu return crypto_shash_init(desc) ?: 159f88ad8deSHerbert Xu crypto_shash_finup(desc, data, len, out); 1607b5a080bSHerbert Xu } 1617b5a080bSHerbert Xu 1627b5a080bSHerbert Xu int crypto_shash_digest(struct shash_desc *desc, const u8 *data, 1637b5a080bSHerbert Xu unsigned int len, u8 *out) 1647b5a080bSHerbert Xu { 1657b5a080bSHerbert Xu struct crypto_shash *tfm = desc->tfm; 1667b5a080bSHerbert Xu struct shash_alg *shash = crypto_shash_alg(tfm); 1677b5a080bSHerbert Xu unsigned long alignmask = crypto_shash_alignmask(tfm); 1687b5a080bSHerbert Xu 1698267adabSHerbert Xu if (((unsigned long)data | (unsigned long)out) & alignmask) 1707b5a080bSHerbert Xu return shash_digest_unaligned(desc, data, len, out); 1717b5a080bSHerbert Xu 1727b5a080bSHerbert Xu return shash->digest(desc, data, len, out); 1737b5a080bSHerbert Xu } 1747b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_shash_digest); 1757b5a080bSHerbert Xu 17699d27e1cSHerbert Xu static int shash_no_export(struct shash_desc *desc, void *out) 177dec8b786SHerbert Xu { 17899d27e1cSHerbert Xu return -ENOSYS; 179dec8b786SHerbert Xu } 18099d27e1cSHerbert Xu 18199d27e1cSHerbert Xu static int shash_no_import(struct shash_desc *desc, const void *in) 18299d27e1cSHerbert Xu { 18399d27e1cSHerbert Xu return -ENOSYS; 18499d27e1cSHerbert Xu } 185dec8b786SHerbert Xu 1863b2f6df0SHerbert Xu static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key, 1873b2f6df0SHerbert Xu unsigned int keylen) 1883b2f6df0SHerbert Xu { 1893b2f6df0SHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(tfm); 1903b2f6df0SHerbert Xu 1913b2f6df0SHerbert Xu return crypto_shash_setkey(*ctx, key, keylen); 1923b2f6df0SHerbert Xu } 1933b2f6df0SHerbert Xu 1943b2f6df0SHerbert Xu static int shash_async_init(struct ahash_request *req) 1953b2f6df0SHerbert Xu { 1963b2f6df0SHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 1973b2f6df0SHerbert Xu struct shash_desc *desc = ahash_request_ctx(req); 1983b2f6df0SHerbert Xu 1993b2f6df0SHerbert Xu desc->tfm = *ctx; 2003b2f6df0SHerbert Xu desc->flags = req->base.flags; 2013b2f6df0SHerbert Xu 2023b2f6df0SHerbert Xu return crypto_shash_init(desc); 2033b2f6df0SHerbert Xu } 2043b2f6df0SHerbert Xu 205*7eddf95eSHerbert Xu int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc) 2063b2f6df0SHerbert Xu { 2073b2f6df0SHerbert Xu struct crypto_hash_walk walk; 2083b2f6df0SHerbert Xu int nbytes; 2093b2f6df0SHerbert Xu 2103b2f6df0SHerbert Xu for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0; 2113b2f6df0SHerbert Xu nbytes = crypto_hash_walk_done(&walk, nbytes)) 2123b2f6df0SHerbert Xu nbytes = crypto_shash_update(desc, walk.data, nbytes); 2133b2f6df0SHerbert Xu 2143b2f6df0SHerbert Xu return nbytes; 2153b2f6df0SHerbert Xu } 216*7eddf95eSHerbert Xu EXPORT_SYMBOL_GPL(shash_ahash_update); 217*7eddf95eSHerbert Xu 218*7eddf95eSHerbert Xu static int shash_async_update(struct ahash_request *req) 219*7eddf95eSHerbert Xu { 220*7eddf95eSHerbert Xu return shash_ahash_update(req, ahash_request_ctx(req)); 221*7eddf95eSHerbert Xu } 2223b2f6df0SHerbert Xu 2233b2f6df0SHerbert Xu static int shash_async_final(struct ahash_request *req) 2243b2f6df0SHerbert Xu { 2253b2f6df0SHerbert Xu return crypto_shash_final(ahash_request_ctx(req), req->result); 2263b2f6df0SHerbert Xu } 2273b2f6df0SHerbert Xu 228*7eddf95eSHerbert Xu int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc) 2293b2f6df0SHerbert Xu { 2303b2f6df0SHerbert Xu struct scatterlist *sg = req->src; 2313b2f6df0SHerbert Xu unsigned int offset = sg->offset; 2323b2f6df0SHerbert Xu unsigned int nbytes = req->nbytes; 2333b2f6df0SHerbert Xu int err; 2343b2f6df0SHerbert Xu 2353b2f6df0SHerbert Xu if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) { 2363b2f6df0SHerbert Xu void *data; 2373b2f6df0SHerbert Xu 2383b2f6df0SHerbert Xu data = crypto_kmap(sg_page(sg), 0); 2393b2f6df0SHerbert Xu err = crypto_shash_digest(desc, data + offset, nbytes, 2403b2f6df0SHerbert Xu req->result); 2413b2f6df0SHerbert Xu crypto_kunmap(data, 0); 2423b2f6df0SHerbert Xu crypto_yield(desc->flags); 243*7eddf95eSHerbert Xu } else 244*7eddf95eSHerbert Xu err = crypto_shash_init(desc) ?: 245*7eddf95eSHerbert Xu shash_ahash_update(req, desc) ?: 246*7eddf95eSHerbert Xu crypto_shash_final(desc, req->result); 2473b2f6df0SHerbert Xu 2483b2f6df0SHerbert Xu return err; 2493b2f6df0SHerbert Xu } 250*7eddf95eSHerbert Xu EXPORT_SYMBOL_GPL(shash_ahash_digest); 251*7eddf95eSHerbert Xu 252*7eddf95eSHerbert Xu static int shash_async_digest(struct ahash_request *req) 253*7eddf95eSHerbert Xu { 254*7eddf95eSHerbert Xu struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 255*7eddf95eSHerbert Xu struct shash_desc *desc = ahash_request_ctx(req); 256*7eddf95eSHerbert Xu 257*7eddf95eSHerbert Xu desc->tfm = *ctx; 258*7eddf95eSHerbert Xu desc->flags = req->base.flags; 259*7eddf95eSHerbert Xu 260*7eddf95eSHerbert Xu return shash_ahash_digest(req, desc); 261*7eddf95eSHerbert Xu } 2623b2f6df0SHerbert Xu 2633b2f6df0SHerbert Xu static void crypto_exit_shash_ops_async(struct crypto_tfm *tfm) 2643b2f6df0SHerbert Xu { 2653b2f6df0SHerbert Xu struct crypto_shash **ctx = crypto_tfm_ctx(tfm); 2663b2f6df0SHerbert Xu 2673b2f6df0SHerbert Xu crypto_free_shash(*ctx); 2683b2f6df0SHerbert Xu } 2693b2f6df0SHerbert Xu 2703b2f6df0SHerbert Xu static int crypto_init_shash_ops_async(struct crypto_tfm *tfm) 2713b2f6df0SHerbert Xu { 2723b2f6df0SHerbert Xu struct crypto_alg *calg = tfm->__crt_alg; 2733b2f6df0SHerbert Xu struct shash_alg *alg = __crypto_shash_alg(calg); 2743b2f6df0SHerbert Xu struct ahash_tfm *crt = &tfm->crt_ahash; 2753b2f6df0SHerbert Xu struct crypto_shash **ctx = crypto_tfm_ctx(tfm); 2763b2f6df0SHerbert Xu struct crypto_shash *shash; 2773b2f6df0SHerbert Xu 2783b2f6df0SHerbert Xu if (!crypto_mod_get(calg)) 2793b2f6df0SHerbert Xu return -EAGAIN; 2803b2f6df0SHerbert Xu 2813f683d61SHerbert Xu shash = crypto_create_tfm(calg, &crypto_shash_type); 2823b2f6df0SHerbert Xu if (IS_ERR(shash)) { 2833b2f6df0SHerbert Xu crypto_mod_put(calg); 2843b2f6df0SHerbert Xu return PTR_ERR(shash); 2853b2f6df0SHerbert Xu } 2863b2f6df0SHerbert Xu 2873b2f6df0SHerbert Xu *ctx = shash; 2883b2f6df0SHerbert Xu tfm->exit = crypto_exit_shash_ops_async; 2893b2f6df0SHerbert Xu 2903b2f6df0SHerbert Xu crt->init = shash_async_init; 2913b2f6df0SHerbert Xu crt->update = shash_async_update; 2923b2f6df0SHerbert Xu crt->final = shash_async_final; 2933b2f6df0SHerbert Xu crt->digest = shash_async_digest; 2943b2f6df0SHerbert Xu crt->setkey = shash_async_setkey; 2953b2f6df0SHerbert Xu 2963b2f6df0SHerbert Xu crt->digestsize = alg->digestsize; 2973b2f6df0SHerbert Xu crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash); 2983b2f6df0SHerbert Xu 2993b2f6df0SHerbert Xu return 0; 3003b2f6df0SHerbert Xu } 3013b2f6df0SHerbert Xu 3025f7082edSHerbert Xu static int shash_compat_setkey(struct crypto_hash *tfm, const u8 *key, 3035f7082edSHerbert Xu unsigned int keylen) 3045f7082edSHerbert Xu { 305113adefcSHerbert Xu struct shash_desc **descp = crypto_hash_ctx(tfm); 306113adefcSHerbert Xu struct shash_desc *desc = *descp; 3075f7082edSHerbert Xu 3085f7082edSHerbert Xu return crypto_shash_setkey(desc->tfm, key, keylen); 3095f7082edSHerbert Xu } 3105f7082edSHerbert Xu 3115f7082edSHerbert Xu static int shash_compat_init(struct hash_desc *hdesc) 3125f7082edSHerbert Xu { 313113adefcSHerbert Xu struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm); 314113adefcSHerbert Xu struct shash_desc *desc = *descp; 3155f7082edSHerbert Xu 3165f7082edSHerbert Xu desc->flags = hdesc->flags; 3175f7082edSHerbert Xu 3185f7082edSHerbert Xu return crypto_shash_init(desc); 3195f7082edSHerbert Xu } 3205f7082edSHerbert Xu 3215f7082edSHerbert Xu static int shash_compat_update(struct hash_desc *hdesc, struct scatterlist *sg, 3225f7082edSHerbert Xu unsigned int len) 3235f7082edSHerbert Xu { 324113adefcSHerbert Xu struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm); 325113adefcSHerbert Xu struct shash_desc *desc = *descp; 3265f7082edSHerbert Xu struct crypto_hash_walk walk; 3275f7082edSHerbert Xu int nbytes; 3285f7082edSHerbert Xu 3295f7082edSHerbert Xu for (nbytes = crypto_hash_walk_first_compat(hdesc, &walk, sg, len); 3305f7082edSHerbert Xu nbytes > 0; nbytes = crypto_hash_walk_done(&walk, nbytes)) 3315f7082edSHerbert Xu nbytes = crypto_shash_update(desc, walk.data, nbytes); 3325f7082edSHerbert Xu 3335f7082edSHerbert Xu return nbytes; 3345f7082edSHerbert Xu } 3355f7082edSHerbert Xu 3365f7082edSHerbert Xu static int shash_compat_final(struct hash_desc *hdesc, u8 *out) 3375f7082edSHerbert Xu { 338113adefcSHerbert Xu struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm); 339113adefcSHerbert Xu 340113adefcSHerbert Xu return crypto_shash_final(*descp, out); 3415f7082edSHerbert Xu } 3425f7082edSHerbert Xu 3435f7082edSHerbert Xu static int shash_compat_digest(struct hash_desc *hdesc, struct scatterlist *sg, 3445f7082edSHerbert Xu unsigned int nbytes, u8 *out) 3455f7082edSHerbert Xu { 3465f7082edSHerbert Xu unsigned int offset = sg->offset; 3475f7082edSHerbert Xu int err; 3485f7082edSHerbert Xu 3495f7082edSHerbert Xu if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) { 350113adefcSHerbert Xu struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm); 351113adefcSHerbert Xu struct shash_desc *desc = *descp; 3525f7082edSHerbert Xu void *data; 3535f7082edSHerbert Xu 3545f7082edSHerbert Xu desc->flags = hdesc->flags; 3555f7082edSHerbert Xu 3565f7082edSHerbert Xu data = crypto_kmap(sg_page(sg), 0); 3575f7082edSHerbert Xu err = crypto_shash_digest(desc, data + offset, nbytes, out); 3585f7082edSHerbert Xu crypto_kunmap(data, 0); 3595f7082edSHerbert Xu crypto_yield(desc->flags); 3605f7082edSHerbert Xu goto out; 3615f7082edSHerbert Xu } 3625f7082edSHerbert Xu 3635f7082edSHerbert Xu err = shash_compat_init(hdesc); 3645f7082edSHerbert Xu if (err) 3655f7082edSHerbert Xu goto out; 3665f7082edSHerbert Xu 3675f7082edSHerbert Xu err = shash_compat_update(hdesc, sg, nbytes); 3685f7082edSHerbert Xu if (err) 3695f7082edSHerbert Xu goto out; 3705f7082edSHerbert Xu 3715f7082edSHerbert Xu err = shash_compat_final(hdesc, out); 3725f7082edSHerbert Xu 3735f7082edSHerbert Xu out: 3745f7082edSHerbert Xu return err; 3755f7082edSHerbert Xu } 3765f7082edSHerbert Xu 3775f7082edSHerbert Xu static void crypto_exit_shash_ops_compat(struct crypto_tfm *tfm) 3785f7082edSHerbert Xu { 379113adefcSHerbert Xu struct shash_desc **descp = crypto_tfm_ctx(tfm); 380113adefcSHerbert Xu struct shash_desc *desc = *descp; 3815f7082edSHerbert Xu 3825f7082edSHerbert Xu crypto_free_shash(desc->tfm); 383113adefcSHerbert Xu kzfree(desc); 3845f7082edSHerbert Xu } 3855f7082edSHerbert Xu 3865f7082edSHerbert Xu static int crypto_init_shash_ops_compat(struct crypto_tfm *tfm) 3875f7082edSHerbert Xu { 3885f7082edSHerbert Xu struct hash_tfm *crt = &tfm->crt_hash; 3895f7082edSHerbert Xu struct crypto_alg *calg = tfm->__crt_alg; 3905f7082edSHerbert Xu struct shash_alg *alg = __crypto_shash_alg(calg); 391113adefcSHerbert Xu struct shash_desc **descp = crypto_tfm_ctx(tfm); 3925f7082edSHerbert Xu struct crypto_shash *shash; 393113adefcSHerbert Xu struct shash_desc *desc; 3945f7082edSHerbert Xu 3954abfd73eSAdrian-Ken Rueegsegger if (!crypto_mod_get(calg)) 3964abfd73eSAdrian-Ken Rueegsegger return -EAGAIN; 3974abfd73eSAdrian-Ken Rueegsegger 3983f683d61SHerbert Xu shash = crypto_create_tfm(calg, &crypto_shash_type); 3994abfd73eSAdrian-Ken Rueegsegger if (IS_ERR(shash)) { 4004abfd73eSAdrian-Ken Rueegsegger crypto_mod_put(calg); 4015f7082edSHerbert Xu return PTR_ERR(shash); 4024abfd73eSAdrian-Ken Rueegsegger } 4035f7082edSHerbert Xu 404113adefcSHerbert Xu desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(shash), 405113adefcSHerbert Xu GFP_KERNEL); 406113adefcSHerbert Xu if (!desc) { 407113adefcSHerbert Xu crypto_free_shash(shash); 408113adefcSHerbert Xu return -ENOMEM; 409113adefcSHerbert Xu } 410113adefcSHerbert Xu 411113adefcSHerbert Xu *descp = desc; 4125f7082edSHerbert Xu desc->tfm = shash; 4135f7082edSHerbert Xu tfm->exit = crypto_exit_shash_ops_compat; 4145f7082edSHerbert Xu 4155f7082edSHerbert Xu crt->init = shash_compat_init; 4165f7082edSHerbert Xu crt->update = shash_compat_update; 4175f7082edSHerbert Xu crt->final = shash_compat_final; 4185f7082edSHerbert Xu crt->digest = shash_compat_digest; 4195f7082edSHerbert Xu crt->setkey = shash_compat_setkey; 4205f7082edSHerbert Xu 4215f7082edSHerbert Xu crt->digestsize = alg->digestsize; 4225f7082edSHerbert Xu 4235f7082edSHerbert Xu return 0; 4245f7082edSHerbert Xu } 4255f7082edSHerbert Xu 4263b2f6df0SHerbert Xu static int crypto_init_shash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) 4273b2f6df0SHerbert Xu { 4283b2f6df0SHerbert Xu switch (mask & CRYPTO_ALG_TYPE_MASK) { 4295f7082edSHerbert Xu case CRYPTO_ALG_TYPE_HASH_MASK: 4305f7082edSHerbert Xu return crypto_init_shash_ops_compat(tfm); 4313b2f6df0SHerbert Xu case CRYPTO_ALG_TYPE_AHASH_MASK: 4323b2f6df0SHerbert Xu return crypto_init_shash_ops_async(tfm); 4333b2f6df0SHerbert Xu } 4343b2f6df0SHerbert Xu 4353b2f6df0SHerbert Xu return -EINVAL; 4363b2f6df0SHerbert Xu } 4373b2f6df0SHerbert Xu 4383b2f6df0SHerbert Xu static unsigned int crypto_shash_ctxsize(struct crypto_alg *alg, u32 type, 4393b2f6df0SHerbert Xu u32 mask) 4403b2f6df0SHerbert Xu { 4413b2f6df0SHerbert Xu switch (mask & CRYPTO_ALG_TYPE_MASK) { 4425f7082edSHerbert Xu case CRYPTO_ALG_TYPE_HASH_MASK: 443113adefcSHerbert Xu return sizeof(struct shash_desc *); 4443b2f6df0SHerbert Xu case CRYPTO_ALG_TYPE_AHASH_MASK: 4453b2f6df0SHerbert Xu return sizeof(struct crypto_shash *); 4463b2f6df0SHerbert Xu } 4473b2f6df0SHerbert Xu 4483b2f6df0SHerbert Xu return 0; 4493b2f6df0SHerbert Xu } 4503b2f6df0SHerbert Xu 4517b5a080bSHerbert Xu static int crypto_shash_init_tfm(struct crypto_tfm *tfm, 4527b5a080bSHerbert Xu const struct crypto_type *frontend) 4537b5a080bSHerbert Xu { 454113adefcSHerbert Xu struct crypto_shash *hash = __crypto_shash_cast(tfm); 455113adefcSHerbert Xu 456113adefcSHerbert Xu hash->descsize = crypto_shash_alg(hash)->descsize; 4577b5a080bSHerbert Xu return 0; 4587b5a080bSHerbert Xu } 4597b5a080bSHerbert Xu 4607b5a080bSHerbert Xu static unsigned int crypto_shash_extsize(struct crypto_alg *alg, 4617b5a080bSHerbert Xu const struct crypto_type *frontend) 4627b5a080bSHerbert Xu { 4637b5a080bSHerbert Xu return alg->cra_ctxsize; 4647b5a080bSHerbert Xu } 4657b5a080bSHerbert Xu 4667b5a080bSHerbert Xu static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg) 4677b5a080bSHerbert Xu __attribute__ ((unused)); 4687b5a080bSHerbert Xu static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg) 4697b5a080bSHerbert Xu { 4707b5a080bSHerbert Xu struct shash_alg *salg = __crypto_shash_alg(alg); 4717b5a080bSHerbert Xu 4727b5a080bSHerbert Xu seq_printf(m, "type : shash\n"); 4737b5a080bSHerbert Xu seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); 4747b5a080bSHerbert Xu seq_printf(m, "digestsize : %u\n", salg->digestsize); 4757b5a080bSHerbert Xu } 4767b5a080bSHerbert Xu 4777b5a080bSHerbert Xu static const struct crypto_type crypto_shash_type = { 4783b2f6df0SHerbert Xu .ctxsize = crypto_shash_ctxsize, 4797b5a080bSHerbert Xu .extsize = crypto_shash_extsize, 4803b2f6df0SHerbert Xu .init = crypto_init_shash_ops, 4817b5a080bSHerbert Xu .init_tfm = crypto_shash_init_tfm, 4827b5a080bSHerbert Xu #ifdef CONFIG_PROC_FS 4837b5a080bSHerbert Xu .show = crypto_shash_show, 4847b5a080bSHerbert Xu #endif 4857b5a080bSHerbert Xu .maskclear = ~CRYPTO_ALG_TYPE_MASK, 4867b5a080bSHerbert Xu .maskset = CRYPTO_ALG_TYPE_MASK, 4877b5a080bSHerbert Xu .type = CRYPTO_ALG_TYPE_SHASH, 4887b5a080bSHerbert Xu .tfmsize = offsetof(struct crypto_shash, base), 4897b5a080bSHerbert Xu }; 4907b5a080bSHerbert Xu 4917b5a080bSHerbert Xu struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type, 4927b5a080bSHerbert Xu u32 mask) 4937b5a080bSHerbert Xu { 4943f683d61SHerbert Xu return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask); 4957b5a080bSHerbert Xu } 4967b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_alloc_shash); 4977b5a080bSHerbert Xu 498619a6ebdSHerbert Xu static int shash_prepare_alg(struct shash_alg *alg) 4997b5a080bSHerbert Xu { 5007b5a080bSHerbert Xu struct crypto_alg *base = &alg->base; 5017b5a080bSHerbert Xu 5027b5a080bSHerbert Xu if (alg->digestsize > PAGE_SIZE / 8 || 50399d27e1cSHerbert Xu alg->descsize > PAGE_SIZE / 8 || 50499d27e1cSHerbert Xu alg->statesize > PAGE_SIZE / 8) 5057b5a080bSHerbert Xu return -EINVAL; 5067b5a080bSHerbert Xu 5077b5a080bSHerbert Xu base->cra_type = &crypto_shash_type; 5087b5a080bSHerbert Xu base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; 5097b5a080bSHerbert Xu base->cra_flags |= CRYPTO_ALG_TYPE_SHASH; 51099d27e1cSHerbert Xu 5118267adabSHerbert Xu if (!alg->finup) 5128267adabSHerbert Xu alg->finup = shash_finup_unaligned; 5138267adabSHerbert Xu if (!alg->digest) 5148267adabSHerbert Xu alg->digest = shash_digest_unaligned; 51599d27e1cSHerbert Xu if (!alg->import) 51699d27e1cSHerbert Xu alg->import = shash_no_import; 51799d27e1cSHerbert Xu if (!alg->export) 51899d27e1cSHerbert Xu alg->export = shash_no_export; 51957cfe44bSHerbert Xu if (!alg->setkey) 52057cfe44bSHerbert Xu alg->setkey = shash_no_setkey; 52199d27e1cSHerbert Xu 522619a6ebdSHerbert Xu return 0; 523619a6ebdSHerbert Xu } 524619a6ebdSHerbert Xu 525619a6ebdSHerbert Xu int crypto_register_shash(struct shash_alg *alg) 526619a6ebdSHerbert Xu { 527619a6ebdSHerbert Xu struct crypto_alg *base = &alg->base; 528619a6ebdSHerbert Xu int err; 529619a6ebdSHerbert Xu 530619a6ebdSHerbert Xu err = shash_prepare_alg(alg); 531619a6ebdSHerbert Xu if (err) 532619a6ebdSHerbert Xu return err; 5337b5a080bSHerbert Xu 5347b5a080bSHerbert Xu return crypto_register_alg(base); 5357b5a080bSHerbert Xu } 5367b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_register_shash); 5377b5a080bSHerbert Xu 5387b5a080bSHerbert Xu int crypto_unregister_shash(struct shash_alg *alg) 5397b5a080bSHerbert Xu { 5407b5a080bSHerbert Xu return crypto_unregister_alg(&alg->base); 5417b5a080bSHerbert Xu } 5427b5a080bSHerbert Xu EXPORT_SYMBOL_GPL(crypto_unregister_shash); 5437b5a080bSHerbert Xu 544619a6ebdSHerbert Xu int shash_register_instance(struct crypto_template *tmpl, 545619a6ebdSHerbert Xu struct shash_instance *inst) 546619a6ebdSHerbert Xu { 547619a6ebdSHerbert Xu int err; 548619a6ebdSHerbert Xu 549619a6ebdSHerbert Xu err = shash_prepare_alg(&inst->alg); 550619a6ebdSHerbert Xu if (err) 551619a6ebdSHerbert Xu return err; 552619a6ebdSHerbert Xu 553619a6ebdSHerbert Xu return crypto_register_instance(tmpl, shash_crypto_instance(inst)); 554619a6ebdSHerbert Xu } 555619a6ebdSHerbert Xu EXPORT_SYMBOL_GPL(shash_register_instance); 556619a6ebdSHerbert Xu 5572e4fddd8SHerbert Xu void shash_free_instance(struct crypto_instance *inst) 5582e4fddd8SHerbert Xu { 5592e4fddd8SHerbert Xu crypto_drop_spawn(crypto_instance_ctx(inst)); 5602e4fddd8SHerbert Xu kfree(shash_instance(inst)); 5612e4fddd8SHerbert Xu } 5622e4fddd8SHerbert Xu EXPORT_SYMBOL_GPL(shash_free_instance); 5632e4fddd8SHerbert Xu 56494296999SHerbert Xu int crypto_init_shash_spawn(struct crypto_shash_spawn *spawn, 56594296999SHerbert Xu struct shash_alg *alg, 56694296999SHerbert Xu struct crypto_instance *inst) 56794296999SHerbert Xu { 56894296999SHerbert Xu return crypto_init_spawn2(&spawn->base, &alg->base, inst, 56994296999SHerbert Xu &crypto_shash_type); 57094296999SHerbert Xu } 57194296999SHerbert Xu EXPORT_SYMBOL_GPL(crypto_init_shash_spawn); 57294296999SHerbert Xu 5737d6f5640SHerbert Xu struct shash_alg *shash_attr_alg(struct rtattr *rta, u32 type, u32 mask) 5747d6f5640SHerbert Xu { 5757d6f5640SHerbert Xu struct crypto_alg *alg; 5767d6f5640SHerbert Xu 5777d6f5640SHerbert Xu alg = crypto_attr_alg2(rta, &crypto_shash_type, type, mask); 5787d6f5640SHerbert Xu return IS_ERR(alg) ? ERR_CAST(alg) : 5797d6f5640SHerbert Xu container_of(alg, struct shash_alg, base); 5807d6f5640SHerbert Xu } 5817d6f5640SHerbert Xu EXPORT_SYMBOL_GPL(shash_attr_alg); 5827d6f5640SHerbert Xu 5837b5a080bSHerbert Xu MODULE_LICENSE("GPL"); 5847b5a080bSHerbert Xu MODULE_DESCRIPTION("Synchronous cryptographic hash type"); 585