18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Asynchronous Compression operations 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2016, Intel Corporation 68c2ecf20Sopenharmony_ci * Authors: Weigang Li <weigang.li@intel.com> 78c2ecf20Sopenharmony_ci * Giovanni Cabiddu <giovanni.cabiddu@intel.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/errno.h> 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 138c2ecf20Sopenharmony_ci#include <linux/slab.h> 148c2ecf20Sopenharmony_ci#include <linux/string.h> 158c2ecf20Sopenharmony_ci#include <linux/crypto.h> 168c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 178c2ecf20Sopenharmony_ci#include <linux/cryptouser.h> 188c2ecf20Sopenharmony_ci#include <linux/compiler.h> 198c2ecf20Sopenharmony_ci#include <net/netlink.h> 208c2ecf20Sopenharmony_ci#include <crypto/internal/acompress.h> 218c2ecf20Sopenharmony_ci#include <crypto/internal/scompress.h> 228c2ecf20Sopenharmony_ci#include "internal.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic const struct crypto_type crypto_acomp_type; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#ifdef CONFIG_NET 278c2ecf20Sopenharmony_cistatic int crypto_acomp_report(struct sk_buff *skb, struct crypto_alg *alg) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci struct crypto_report_acomp racomp; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci memset(&racomp, 0, sizeof(racomp)); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci strscpy(racomp.type, "acomp", sizeof(racomp.type)); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci return nla_put(skb, CRYPTOCFGA_REPORT_ACOMP, sizeof(racomp), &racomp); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci#else 388c2ecf20Sopenharmony_cistatic int crypto_acomp_report(struct sk_buff *skb, struct crypto_alg *alg) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci return -ENOSYS; 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci#endif 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic void crypto_acomp_show(struct seq_file *m, struct crypto_alg *alg) 458c2ecf20Sopenharmony_ci __maybe_unused; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic void crypto_acomp_show(struct seq_file *m, struct crypto_alg *alg) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci seq_puts(m, "type : acomp\n"); 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic void crypto_acomp_exit_tfm(struct crypto_tfm *tfm) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci struct crypto_acomp *acomp = __crypto_acomp_tfm(tfm); 558c2ecf20Sopenharmony_ci struct acomp_alg *alg = crypto_acomp_alg(acomp); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci alg->exit(acomp); 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic int crypto_acomp_init_tfm(struct crypto_tfm *tfm) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci struct crypto_acomp *acomp = __crypto_acomp_tfm(tfm); 638c2ecf20Sopenharmony_ci struct acomp_alg *alg = crypto_acomp_alg(acomp); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci if (tfm->__crt_alg->cra_type != &crypto_acomp_type) 668c2ecf20Sopenharmony_ci return crypto_init_scomp_ops_async(tfm); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci acomp->compress = alg->compress; 698c2ecf20Sopenharmony_ci acomp->decompress = alg->decompress; 708c2ecf20Sopenharmony_ci acomp->dst_free = alg->dst_free; 718c2ecf20Sopenharmony_ci acomp->reqsize = alg->reqsize; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci if (alg->exit) 748c2ecf20Sopenharmony_ci acomp->base.exit = crypto_acomp_exit_tfm; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci if (alg->init) 778c2ecf20Sopenharmony_ci return alg->init(acomp); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci return 0; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic unsigned int crypto_acomp_extsize(struct crypto_alg *alg) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci int extsize = crypto_alg_extsize(alg); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci if (alg->cra_type != &crypto_acomp_type) 878c2ecf20Sopenharmony_ci extsize += sizeof(struct crypto_scomp *); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci return extsize; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic const struct crypto_type crypto_acomp_type = { 938c2ecf20Sopenharmony_ci .extsize = crypto_acomp_extsize, 948c2ecf20Sopenharmony_ci .init_tfm = crypto_acomp_init_tfm, 958c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 968c2ecf20Sopenharmony_ci .show = crypto_acomp_show, 978c2ecf20Sopenharmony_ci#endif 988c2ecf20Sopenharmony_ci .report = crypto_acomp_report, 998c2ecf20Sopenharmony_ci .maskclear = ~CRYPTO_ALG_TYPE_MASK, 1008c2ecf20Sopenharmony_ci .maskset = CRYPTO_ALG_TYPE_ACOMPRESS_MASK, 1018c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_ACOMPRESS, 1028c2ecf20Sopenharmony_ci .tfmsize = offsetof(struct crypto_acomp, base), 1038c2ecf20Sopenharmony_ci}; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistruct crypto_acomp *crypto_alloc_acomp(const char *alg_name, u32 type, 1068c2ecf20Sopenharmony_ci u32 mask) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci return crypto_alloc_tfm(alg_name, &crypto_acomp_type, type, mask); 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_alloc_acomp); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistruct crypto_acomp *crypto_alloc_acomp_node(const char *alg_name, u32 type, 1138c2ecf20Sopenharmony_ci u32 mask, int node) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci return crypto_alloc_tfm_node(alg_name, &crypto_acomp_type, type, mask, 1168c2ecf20Sopenharmony_ci node); 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_alloc_acomp_node); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistruct acomp_req *acomp_request_alloc(struct crypto_acomp *acomp) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_acomp_tfm(acomp); 1238c2ecf20Sopenharmony_ci struct acomp_req *req; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci req = __acomp_request_alloc(acomp); 1268c2ecf20Sopenharmony_ci if (req && (tfm->__crt_alg->cra_type != &crypto_acomp_type)) 1278c2ecf20Sopenharmony_ci return crypto_acomp_scomp_alloc_ctx(req); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci return req; 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(acomp_request_alloc); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_civoid acomp_request_free(struct acomp_req *req) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci struct crypto_acomp *acomp = crypto_acomp_reqtfm(req); 1368c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_acomp_tfm(acomp); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci if (tfm->__crt_alg->cra_type != &crypto_acomp_type) 1398c2ecf20Sopenharmony_ci crypto_acomp_scomp_free_ctx(req); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci if (req->flags & CRYPTO_ACOMP_ALLOC_OUTPUT) { 1428c2ecf20Sopenharmony_ci acomp->dst_free(req->dst); 1438c2ecf20Sopenharmony_ci req->dst = NULL; 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci __acomp_request_free(req); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(acomp_request_free); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ciint crypto_register_acomp(struct acomp_alg *alg) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci struct crypto_alg *base = &alg->base; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci base->cra_type = &crypto_acomp_type; 1558c2ecf20Sopenharmony_ci base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; 1568c2ecf20Sopenharmony_ci base->cra_flags |= CRYPTO_ALG_TYPE_ACOMPRESS; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci return crypto_register_alg(base); 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_register_acomp); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_civoid crypto_unregister_acomp(struct acomp_alg *alg) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci crypto_unregister_alg(&alg->base); 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_unregister_acomp); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ciint crypto_register_acomps(struct acomp_alg *algs, int count) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci int i, ret; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) { 1738c2ecf20Sopenharmony_ci ret = crypto_register_acomp(&algs[i]); 1748c2ecf20Sopenharmony_ci if (ret) 1758c2ecf20Sopenharmony_ci goto err; 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci return 0; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_cierr: 1818c2ecf20Sopenharmony_ci for (--i; i >= 0; --i) 1828c2ecf20Sopenharmony_ci crypto_unregister_acomp(&algs[i]); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci return ret; 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_register_acomps); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_civoid crypto_unregister_acomps(struct acomp_alg *algs, int count) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci int i; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci for (i = count - 1; i >= 0; --i) 1938c2ecf20Sopenharmony_ci crypto_unregister_acomp(&algs[i]); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_unregister_acomps); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1988c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Asynchronous compression type"); 199