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