18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Synchronous Cryptographic Hash operations. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 98c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h> 108c2ecf20Sopenharmony_ci#include <linux/err.h> 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/slab.h> 148c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 158c2ecf20Sopenharmony_ci#include <linux/cryptouser.h> 168c2ecf20Sopenharmony_ci#include <net/netlink.h> 178c2ecf20Sopenharmony_ci#include <linux/compiler.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "internal.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic const struct crypto_type crypto_shash_type; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, 248c2ecf20Sopenharmony_ci unsigned int keylen) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci return -ENOSYS; 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* 308c2ecf20Sopenharmony_ci * Check whether an shash algorithm has a setkey function. 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * For CFI compatibility, this must not be an inline function. This is because 338c2ecf20Sopenharmony_ci * when CFI is enabled, modules won't get the same address for shash_no_setkey 348c2ecf20Sopenharmony_ci * (if it were exported, which inlining would require) as the core kernel will. 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_cibool crypto_shash_alg_has_setkey(struct shash_alg *alg) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci return alg->setkey != shash_no_setkey; 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_shash_alg_has_setkey); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key, 438c2ecf20Sopenharmony_ci unsigned int keylen) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci struct shash_alg *shash = crypto_shash_alg(tfm); 468c2ecf20Sopenharmony_ci unsigned long alignmask = crypto_shash_alignmask(tfm); 478c2ecf20Sopenharmony_ci unsigned long absize; 488c2ecf20Sopenharmony_ci u8 *buffer, *alignbuffer; 498c2ecf20Sopenharmony_ci int err; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci absize = keylen + (alignmask & ~(crypto_tfm_ctx_alignment() - 1)); 528c2ecf20Sopenharmony_ci buffer = kmalloc(absize, GFP_ATOMIC); 538c2ecf20Sopenharmony_ci if (!buffer) 548c2ecf20Sopenharmony_ci return -ENOMEM; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); 578c2ecf20Sopenharmony_ci memcpy(alignbuffer, key, keylen); 588c2ecf20Sopenharmony_ci err = shash->setkey(tfm, alignbuffer, keylen); 598c2ecf20Sopenharmony_ci kfree_sensitive(buffer); 608c2ecf20Sopenharmony_ci return err; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic void shash_set_needkey(struct crypto_shash *tfm, struct shash_alg *alg) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci if (crypto_shash_alg_needs_key(alg)) 668c2ecf20Sopenharmony_ci crypto_shash_set_flags(tfm, CRYPTO_TFM_NEED_KEY); 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ciint crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key, 708c2ecf20Sopenharmony_ci unsigned int keylen) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci struct shash_alg *shash = crypto_shash_alg(tfm); 738c2ecf20Sopenharmony_ci unsigned long alignmask = crypto_shash_alignmask(tfm); 748c2ecf20Sopenharmony_ci int err; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci if ((unsigned long)key & alignmask) 778c2ecf20Sopenharmony_ci err = shash_setkey_unaligned(tfm, key, keylen); 788c2ecf20Sopenharmony_ci else 798c2ecf20Sopenharmony_ci err = shash->setkey(tfm, key, keylen); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if (unlikely(err)) { 828c2ecf20Sopenharmony_ci shash_set_needkey(tfm, shash); 838c2ecf20Sopenharmony_ci return err; 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci crypto_shash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY); 878c2ecf20Sopenharmony_ci return 0; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_shash_setkey); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic int shash_update_unaligned(struct shash_desc *desc, const u8 *data, 928c2ecf20Sopenharmony_ci unsigned int len) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci struct crypto_shash *tfm = desc->tfm; 958c2ecf20Sopenharmony_ci struct shash_alg *shash = crypto_shash_alg(tfm); 968c2ecf20Sopenharmony_ci unsigned long alignmask = crypto_shash_alignmask(tfm); 978c2ecf20Sopenharmony_ci unsigned int unaligned_len = alignmask + 1 - 988c2ecf20Sopenharmony_ci ((unsigned long)data & alignmask); 998c2ecf20Sopenharmony_ci /* 1008c2ecf20Sopenharmony_ci * We cannot count on __aligned() working for large values: 1018c2ecf20Sopenharmony_ci * https://patchwork.kernel.org/patch/9507697/ 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci u8 ubuf[MAX_ALGAPI_ALIGNMASK * 2]; 1048c2ecf20Sopenharmony_ci u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1); 1058c2ecf20Sopenharmony_ci int err; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci if (WARN_ON(buf + unaligned_len > ubuf + sizeof(ubuf))) 1088c2ecf20Sopenharmony_ci return -EINVAL; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (unaligned_len > len) 1118c2ecf20Sopenharmony_ci unaligned_len = len; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci memcpy(buf, data, unaligned_len); 1148c2ecf20Sopenharmony_ci err = shash->update(desc, buf, unaligned_len); 1158c2ecf20Sopenharmony_ci memset(buf, 0, unaligned_len); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci return err ?: 1188c2ecf20Sopenharmony_ci shash->update(desc, data + unaligned_len, len - unaligned_len); 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ciint crypto_shash_update(struct shash_desc *desc, const u8 *data, 1228c2ecf20Sopenharmony_ci unsigned int len) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci struct crypto_shash *tfm = desc->tfm; 1258c2ecf20Sopenharmony_ci struct shash_alg *shash = crypto_shash_alg(tfm); 1268c2ecf20Sopenharmony_ci unsigned long alignmask = crypto_shash_alignmask(tfm); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if ((unsigned long)data & alignmask) 1298c2ecf20Sopenharmony_ci return shash_update_unaligned(desc, data, len); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci return shash->update(desc, data, len); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_shash_update); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic int shash_final_unaligned(struct shash_desc *desc, u8 *out) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci struct crypto_shash *tfm = desc->tfm; 1388c2ecf20Sopenharmony_ci unsigned long alignmask = crypto_shash_alignmask(tfm); 1398c2ecf20Sopenharmony_ci struct shash_alg *shash = crypto_shash_alg(tfm); 1408c2ecf20Sopenharmony_ci unsigned int ds = crypto_shash_digestsize(tfm); 1418c2ecf20Sopenharmony_ci /* 1428c2ecf20Sopenharmony_ci * We cannot count on __aligned() working for large values: 1438c2ecf20Sopenharmony_ci * https://patchwork.kernel.org/patch/9507697/ 1448c2ecf20Sopenharmony_ci */ 1458c2ecf20Sopenharmony_ci u8 ubuf[MAX_ALGAPI_ALIGNMASK + HASH_MAX_DIGESTSIZE]; 1468c2ecf20Sopenharmony_ci u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1); 1478c2ecf20Sopenharmony_ci int err; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci if (WARN_ON(buf + ds > ubuf + sizeof(ubuf))) 1508c2ecf20Sopenharmony_ci return -EINVAL; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci err = shash->final(desc, buf); 1538c2ecf20Sopenharmony_ci if (err) 1548c2ecf20Sopenharmony_ci goto out; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci memcpy(out, buf, ds); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ciout: 1598c2ecf20Sopenharmony_ci memset(buf, 0, ds); 1608c2ecf20Sopenharmony_ci return err; 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ciint crypto_shash_final(struct shash_desc *desc, u8 *out) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci struct crypto_shash *tfm = desc->tfm; 1668c2ecf20Sopenharmony_ci struct shash_alg *shash = crypto_shash_alg(tfm); 1678c2ecf20Sopenharmony_ci unsigned long alignmask = crypto_shash_alignmask(tfm); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci if ((unsigned long)out & alignmask) 1708c2ecf20Sopenharmony_ci return shash_final_unaligned(desc, out); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci return shash->final(desc, out); 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_shash_final); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cistatic int shash_finup_unaligned(struct shash_desc *desc, const u8 *data, 1778c2ecf20Sopenharmony_ci unsigned int len, u8 *out) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci return crypto_shash_update(desc, data, len) ?: 1808c2ecf20Sopenharmony_ci crypto_shash_final(desc, out); 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ciint crypto_shash_finup(struct shash_desc *desc, const u8 *data, 1848c2ecf20Sopenharmony_ci unsigned int len, u8 *out) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci struct crypto_shash *tfm = desc->tfm; 1878c2ecf20Sopenharmony_ci struct shash_alg *shash = crypto_shash_alg(tfm); 1888c2ecf20Sopenharmony_ci unsigned long alignmask = crypto_shash_alignmask(tfm); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci if (((unsigned long)data | (unsigned long)out) & alignmask) 1918c2ecf20Sopenharmony_ci return shash_finup_unaligned(desc, data, len, out); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci return shash->finup(desc, data, len, out); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_shash_finup); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int shash_digest_unaligned(struct shash_desc *desc, const u8 *data, 1988c2ecf20Sopenharmony_ci unsigned int len, u8 *out) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci return crypto_shash_init(desc) ?: 2018c2ecf20Sopenharmony_ci crypto_shash_finup(desc, data, len, out); 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ciint crypto_shash_digest(struct shash_desc *desc, const u8 *data, 2058c2ecf20Sopenharmony_ci unsigned int len, u8 *out) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci struct crypto_shash *tfm = desc->tfm; 2088c2ecf20Sopenharmony_ci struct shash_alg *shash = crypto_shash_alg(tfm); 2098c2ecf20Sopenharmony_ci unsigned long alignmask = crypto_shash_alignmask(tfm); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) 2128c2ecf20Sopenharmony_ci return -ENOKEY; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci if (((unsigned long)data | (unsigned long)out) & alignmask) 2158c2ecf20Sopenharmony_ci return shash_digest_unaligned(desc, data, len, out); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci return shash->digest(desc, data, len, out); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_shash_digest); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ciint crypto_shash_tfm_digest(struct crypto_shash *tfm, const u8 *data, 2228c2ecf20Sopenharmony_ci unsigned int len, u8 *out) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci SHASH_DESC_ON_STACK(desc, tfm); 2258c2ecf20Sopenharmony_ci int err; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci desc->tfm = tfm; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci err = crypto_shash_digest(desc, data, len, out); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci shash_desc_zero(desc); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci return err; 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_shash_tfm_digest); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic int shash_default_export(struct shash_desc *desc, void *out) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(desc->tfm)); 2408c2ecf20Sopenharmony_ci return 0; 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic int shash_default_import(struct shash_desc *desc, const void *in) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(desc->tfm)); 2468c2ecf20Sopenharmony_ci return 0; 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key, 2508c2ecf20Sopenharmony_ci unsigned int keylen) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci struct crypto_shash **ctx = crypto_ahash_ctx(tfm); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci return crypto_shash_setkey(*ctx, key, keylen); 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cistatic int shash_async_init(struct ahash_request *req) 2588c2ecf20Sopenharmony_ci{ 2598c2ecf20Sopenharmony_ci struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 2608c2ecf20Sopenharmony_ci struct shash_desc *desc = ahash_request_ctx(req); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci desc->tfm = *ctx; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci return crypto_shash_init(desc); 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ciint shash_ahash_update(struct ahash_request *req, struct shash_desc *desc) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci struct crypto_hash_walk walk; 2708c2ecf20Sopenharmony_ci int nbytes; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0; 2738c2ecf20Sopenharmony_ci nbytes = crypto_hash_walk_done(&walk, nbytes)) 2748c2ecf20Sopenharmony_ci nbytes = crypto_shash_update(desc, walk.data, nbytes); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci return nbytes; 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(shash_ahash_update); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_cistatic int shash_async_update(struct ahash_request *req) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci return shash_ahash_update(req, ahash_request_ctx(req)); 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic int shash_async_final(struct ahash_request *req) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci return crypto_shash_final(ahash_request_ctx(req), req->result); 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ciint shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci struct crypto_hash_walk walk; 2938c2ecf20Sopenharmony_ci int nbytes; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci nbytes = crypto_hash_walk_first(req, &walk); 2968c2ecf20Sopenharmony_ci if (!nbytes) 2978c2ecf20Sopenharmony_ci return crypto_shash_final(desc, req->result); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci do { 3008c2ecf20Sopenharmony_ci nbytes = crypto_hash_walk_last(&walk) ? 3018c2ecf20Sopenharmony_ci crypto_shash_finup(desc, walk.data, nbytes, 3028c2ecf20Sopenharmony_ci req->result) : 3038c2ecf20Sopenharmony_ci crypto_shash_update(desc, walk.data, nbytes); 3048c2ecf20Sopenharmony_ci nbytes = crypto_hash_walk_done(&walk, nbytes); 3058c2ecf20Sopenharmony_ci } while (nbytes > 0); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci return nbytes; 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(shash_ahash_finup); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic int shash_async_finup(struct ahash_request *req) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 3148c2ecf20Sopenharmony_ci struct shash_desc *desc = ahash_request_ctx(req); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci desc->tfm = *ctx; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci return shash_ahash_finup(req, desc); 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ciint shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci unsigned int nbytes = req->nbytes; 3248c2ecf20Sopenharmony_ci struct scatterlist *sg; 3258c2ecf20Sopenharmony_ci unsigned int offset; 3268c2ecf20Sopenharmony_ci int err; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci if (nbytes && 3298c2ecf20Sopenharmony_ci (sg = req->src, offset = sg->offset, 3308c2ecf20Sopenharmony_ci nbytes <= min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) { 3318c2ecf20Sopenharmony_ci void *data; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci data = kmap_atomic(sg_page(sg)); 3348c2ecf20Sopenharmony_ci err = crypto_shash_digest(desc, data + offset, nbytes, 3358c2ecf20Sopenharmony_ci req->result); 3368c2ecf20Sopenharmony_ci kunmap_atomic(data); 3378c2ecf20Sopenharmony_ci } else 3388c2ecf20Sopenharmony_ci err = crypto_shash_init(desc) ?: 3398c2ecf20Sopenharmony_ci shash_ahash_finup(req, desc); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci return err; 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(shash_ahash_digest); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cistatic int shash_async_digest(struct ahash_request *req) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 3488c2ecf20Sopenharmony_ci struct shash_desc *desc = ahash_request_ctx(req); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci desc->tfm = *ctx; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci return shash_ahash_digest(req, desc); 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic int shash_async_export(struct ahash_request *req, void *out) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci return crypto_shash_export(ahash_request_ctx(req), out); 3588c2ecf20Sopenharmony_ci} 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cistatic int shash_async_import(struct ahash_request *req, const void *in) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 3638c2ecf20Sopenharmony_ci struct shash_desc *desc = ahash_request_ctx(req); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci desc->tfm = *ctx; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci return crypto_shash_import(desc, in); 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_cistatic void crypto_exit_shash_ops_async(struct crypto_tfm *tfm) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci struct crypto_shash **ctx = crypto_tfm_ctx(tfm); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci crypto_free_shash(*ctx); 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ciint crypto_init_shash_ops_async(struct crypto_tfm *tfm) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci struct crypto_alg *calg = tfm->__crt_alg; 3808c2ecf20Sopenharmony_ci struct shash_alg *alg = __crypto_shash_alg(calg); 3818c2ecf20Sopenharmony_ci struct crypto_ahash *crt = __crypto_ahash_cast(tfm); 3828c2ecf20Sopenharmony_ci struct crypto_shash **ctx = crypto_tfm_ctx(tfm); 3838c2ecf20Sopenharmony_ci struct crypto_shash *shash; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (!crypto_mod_get(calg)) 3868c2ecf20Sopenharmony_ci return -EAGAIN; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci shash = crypto_create_tfm(calg, &crypto_shash_type); 3898c2ecf20Sopenharmony_ci if (IS_ERR(shash)) { 3908c2ecf20Sopenharmony_ci crypto_mod_put(calg); 3918c2ecf20Sopenharmony_ci return PTR_ERR(shash); 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci *ctx = shash; 3958c2ecf20Sopenharmony_ci tfm->exit = crypto_exit_shash_ops_async; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci crt->init = shash_async_init; 3988c2ecf20Sopenharmony_ci crt->update = shash_async_update; 3998c2ecf20Sopenharmony_ci crt->final = shash_async_final; 4008c2ecf20Sopenharmony_ci crt->finup = shash_async_finup; 4018c2ecf20Sopenharmony_ci crt->digest = shash_async_digest; 4028c2ecf20Sopenharmony_ci if (crypto_shash_alg_has_setkey(alg)) 4038c2ecf20Sopenharmony_ci crt->setkey = shash_async_setkey; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci crypto_ahash_set_flags(crt, crypto_shash_get_flags(shash) & 4068c2ecf20Sopenharmony_ci CRYPTO_TFM_NEED_KEY); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci crt->export = shash_async_export; 4098c2ecf20Sopenharmony_ci crt->import = shash_async_import; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash); 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci return 0; 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_cistatic void crypto_shash_exit_tfm(struct crypto_tfm *tfm) 4178c2ecf20Sopenharmony_ci{ 4188c2ecf20Sopenharmony_ci struct crypto_shash *hash = __crypto_shash_cast(tfm); 4198c2ecf20Sopenharmony_ci struct shash_alg *alg = crypto_shash_alg(hash); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci alg->exit_tfm(hash); 4228c2ecf20Sopenharmony_ci} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_cistatic int crypto_shash_init_tfm(struct crypto_tfm *tfm) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci struct crypto_shash *hash = __crypto_shash_cast(tfm); 4278c2ecf20Sopenharmony_ci struct shash_alg *alg = crypto_shash_alg(hash); 4288c2ecf20Sopenharmony_ci int err; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci hash->descsize = alg->descsize; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci shash_set_needkey(hash, alg); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci if (alg->exit_tfm) 4358c2ecf20Sopenharmony_ci tfm->exit = crypto_shash_exit_tfm; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci if (!alg->init_tfm) 4388c2ecf20Sopenharmony_ci return 0; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci err = alg->init_tfm(hash); 4418c2ecf20Sopenharmony_ci if (err) 4428c2ecf20Sopenharmony_ci return err; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci /* ->init_tfm() may have increased the descsize. */ 4458c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(hash->descsize > HASH_MAX_DESCSIZE)) { 4468c2ecf20Sopenharmony_ci if (alg->exit_tfm) 4478c2ecf20Sopenharmony_ci alg->exit_tfm(hash); 4488c2ecf20Sopenharmony_ci return -EINVAL; 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci return 0; 4528c2ecf20Sopenharmony_ci} 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_cistatic void crypto_shash_free_instance(struct crypto_instance *inst) 4558c2ecf20Sopenharmony_ci{ 4568c2ecf20Sopenharmony_ci struct shash_instance *shash = shash_instance(inst); 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci shash->free(shash); 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci#ifdef CONFIG_NET 4628c2ecf20Sopenharmony_cistatic int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg) 4638c2ecf20Sopenharmony_ci{ 4648c2ecf20Sopenharmony_ci struct crypto_report_hash rhash; 4658c2ecf20Sopenharmony_ci struct shash_alg *salg = __crypto_shash_alg(alg); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci memset(&rhash, 0, sizeof(rhash)); 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci strscpy(rhash.type, "shash", sizeof(rhash.type)); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci rhash.blocksize = alg->cra_blocksize; 4728c2ecf20Sopenharmony_ci rhash.digestsize = salg->digestsize; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci return nla_put(skb, CRYPTOCFGA_REPORT_HASH, sizeof(rhash), &rhash); 4758c2ecf20Sopenharmony_ci} 4768c2ecf20Sopenharmony_ci#else 4778c2ecf20Sopenharmony_cistatic int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg) 4788c2ecf20Sopenharmony_ci{ 4798c2ecf20Sopenharmony_ci return -ENOSYS; 4808c2ecf20Sopenharmony_ci} 4818c2ecf20Sopenharmony_ci#endif 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_cistatic void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg) 4848c2ecf20Sopenharmony_ci __maybe_unused; 4858c2ecf20Sopenharmony_cistatic void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg) 4868c2ecf20Sopenharmony_ci{ 4878c2ecf20Sopenharmony_ci struct shash_alg *salg = __crypto_shash_alg(alg); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci seq_printf(m, "type : shash\n"); 4908c2ecf20Sopenharmony_ci seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); 4918c2ecf20Sopenharmony_ci seq_printf(m, "digestsize : %u\n", salg->digestsize); 4928c2ecf20Sopenharmony_ci} 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_cistatic const struct crypto_type crypto_shash_type = { 4958c2ecf20Sopenharmony_ci .extsize = crypto_alg_extsize, 4968c2ecf20Sopenharmony_ci .init_tfm = crypto_shash_init_tfm, 4978c2ecf20Sopenharmony_ci .free = crypto_shash_free_instance, 4988c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 4998c2ecf20Sopenharmony_ci .show = crypto_shash_show, 5008c2ecf20Sopenharmony_ci#endif 5018c2ecf20Sopenharmony_ci .report = crypto_shash_report, 5028c2ecf20Sopenharmony_ci .maskclear = ~CRYPTO_ALG_TYPE_MASK, 5038c2ecf20Sopenharmony_ci .maskset = CRYPTO_ALG_TYPE_MASK, 5048c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SHASH, 5058c2ecf20Sopenharmony_ci .tfmsize = offsetof(struct crypto_shash, base), 5068c2ecf20Sopenharmony_ci}; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ciint crypto_grab_shash(struct crypto_shash_spawn *spawn, 5098c2ecf20Sopenharmony_ci struct crypto_instance *inst, 5108c2ecf20Sopenharmony_ci const char *name, u32 type, u32 mask) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci spawn->base.frontend = &crypto_shash_type; 5138c2ecf20Sopenharmony_ci return crypto_grab_spawn(&spawn->base, inst, name, type, mask); 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_grab_shash); 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_cistruct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type, 5188c2ecf20Sopenharmony_ci u32 mask) 5198c2ecf20Sopenharmony_ci{ 5208c2ecf20Sopenharmony_ci return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask); 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_alloc_shash); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_cistatic int shash_prepare_alg(struct shash_alg *alg) 5258c2ecf20Sopenharmony_ci{ 5268c2ecf20Sopenharmony_ci struct crypto_alg *base = &alg->base; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci if (alg->digestsize > HASH_MAX_DIGESTSIZE || 5298c2ecf20Sopenharmony_ci alg->descsize > HASH_MAX_DESCSIZE || 5308c2ecf20Sopenharmony_ci alg->statesize > HASH_MAX_STATESIZE) 5318c2ecf20Sopenharmony_ci return -EINVAL; 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci if ((alg->export && !alg->import) || (alg->import && !alg->export)) 5348c2ecf20Sopenharmony_ci return -EINVAL; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci base->cra_type = &crypto_shash_type; 5378c2ecf20Sopenharmony_ci base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; 5388c2ecf20Sopenharmony_ci base->cra_flags |= CRYPTO_ALG_TYPE_SHASH; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci if (!alg->finup) 5418c2ecf20Sopenharmony_ci alg->finup = shash_finup_unaligned; 5428c2ecf20Sopenharmony_ci if (!alg->digest) 5438c2ecf20Sopenharmony_ci alg->digest = shash_digest_unaligned; 5448c2ecf20Sopenharmony_ci if (!alg->export) { 5458c2ecf20Sopenharmony_ci alg->export = shash_default_export; 5468c2ecf20Sopenharmony_ci alg->import = shash_default_import; 5478c2ecf20Sopenharmony_ci alg->statesize = alg->descsize; 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci if (!alg->setkey) 5508c2ecf20Sopenharmony_ci alg->setkey = shash_no_setkey; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci return 0; 5538c2ecf20Sopenharmony_ci} 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ciint crypto_register_shash(struct shash_alg *alg) 5568c2ecf20Sopenharmony_ci{ 5578c2ecf20Sopenharmony_ci struct crypto_alg *base = &alg->base; 5588c2ecf20Sopenharmony_ci int err; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci err = shash_prepare_alg(alg); 5618c2ecf20Sopenharmony_ci if (err) 5628c2ecf20Sopenharmony_ci return err; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci return crypto_register_alg(base); 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_register_shash); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_civoid crypto_unregister_shash(struct shash_alg *alg) 5698c2ecf20Sopenharmony_ci{ 5708c2ecf20Sopenharmony_ci crypto_unregister_alg(&alg->base); 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_unregister_shash); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ciint crypto_register_shashes(struct shash_alg *algs, int count) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci int i, ret; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) { 5798c2ecf20Sopenharmony_ci ret = crypto_register_shash(&algs[i]); 5808c2ecf20Sopenharmony_ci if (ret) 5818c2ecf20Sopenharmony_ci goto err; 5828c2ecf20Sopenharmony_ci } 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci return 0; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_cierr: 5878c2ecf20Sopenharmony_ci for (--i; i >= 0; --i) 5888c2ecf20Sopenharmony_ci crypto_unregister_shash(&algs[i]); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci return ret; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_register_shashes); 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_civoid crypto_unregister_shashes(struct shash_alg *algs, int count) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci int i; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci for (i = count - 1; i >= 0; --i) 5998c2ecf20Sopenharmony_ci crypto_unregister_shash(&algs[i]); 6008c2ecf20Sopenharmony_ci} 6018c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_unregister_shashes); 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ciint shash_register_instance(struct crypto_template *tmpl, 6048c2ecf20Sopenharmony_ci struct shash_instance *inst) 6058c2ecf20Sopenharmony_ci{ 6068c2ecf20Sopenharmony_ci int err; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci if (WARN_ON(!inst->free)) 6098c2ecf20Sopenharmony_ci return -EINVAL; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci err = shash_prepare_alg(&inst->alg); 6128c2ecf20Sopenharmony_ci if (err) 6138c2ecf20Sopenharmony_ci return err; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci return crypto_register_instance(tmpl, shash_crypto_instance(inst)); 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(shash_register_instance); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_civoid shash_free_singlespawn_instance(struct shash_instance *inst) 6208c2ecf20Sopenharmony_ci{ 6218c2ecf20Sopenharmony_ci crypto_drop_spawn(shash_instance_ctx(inst)); 6228c2ecf20Sopenharmony_ci kfree(inst); 6238c2ecf20Sopenharmony_ci} 6248c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(shash_free_singlespawn_instance); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 6278c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Synchronous cryptographic hash type"); 628