brintos

brintos / linux-shallow public Read only

0
0
Text · 5.0 KiB · 154a969 Raw
259 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Cryptographic API.4 *5 * Copyright (c) 2017-present, Facebook, Inc.6 */7#include <linux/crypto.h>8#include <linux/init.h>9#include <linux/interrupt.h>10#include <linux/mm.h>11#include <linux/module.h>12#include <linux/net.h>13#include <linux/vmalloc.h>14#include <linux/zstd.h>15#include <crypto/internal/scompress.h>16 17 18#define ZSTD_DEF_LEVEL	319 20struct zstd_ctx {21	zstd_cctx *cctx;22	zstd_dctx *dctx;23	void *cwksp;24	void *dwksp;25};26 27static zstd_parameters zstd_params(void)28{29	return zstd_get_params(ZSTD_DEF_LEVEL, 0);30}31 32static int zstd_comp_init(struct zstd_ctx *ctx)33{34	int ret = 0;35	const zstd_parameters params = zstd_params();36	const size_t wksp_size = zstd_cctx_workspace_bound(&params.cParams);37 38	ctx->cwksp = vzalloc(wksp_size);39	if (!ctx->cwksp) {40		ret = -ENOMEM;41		goto out;42	}43 44	ctx->cctx = zstd_init_cctx(ctx->cwksp, wksp_size);45	if (!ctx->cctx) {46		ret = -EINVAL;47		goto out_free;48	}49out:50	return ret;51out_free:52	vfree(ctx->cwksp);53	goto out;54}55 56static int zstd_decomp_init(struct zstd_ctx *ctx)57{58	int ret = 0;59	const size_t wksp_size = zstd_dctx_workspace_bound();60 61	ctx->dwksp = vzalloc(wksp_size);62	if (!ctx->dwksp) {63		ret = -ENOMEM;64		goto out;65	}66 67	ctx->dctx = zstd_init_dctx(ctx->dwksp, wksp_size);68	if (!ctx->dctx) {69		ret = -EINVAL;70		goto out_free;71	}72out:73	return ret;74out_free:75	vfree(ctx->dwksp);76	goto out;77}78 79static void zstd_comp_exit(struct zstd_ctx *ctx)80{81	vfree(ctx->cwksp);82	ctx->cwksp = NULL;83	ctx->cctx = NULL;84}85 86static void zstd_decomp_exit(struct zstd_ctx *ctx)87{88	vfree(ctx->dwksp);89	ctx->dwksp = NULL;90	ctx->dctx = NULL;91}92 93static int __zstd_init(void *ctx)94{95	int ret;96 97	ret = zstd_comp_init(ctx);98	if (ret)99		return ret;100	ret = zstd_decomp_init(ctx);101	if (ret)102		zstd_comp_exit(ctx);103	return ret;104}105 106static void *zstd_alloc_ctx(struct crypto_scomp *tfm)107{108	int ret;109	struct zstd_ctx *ctx;110 111	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);112	if (!ctx)113		return ERR_PTR(-ENOMEM);114 115	ret = __zstd_init(ctx);116	if (ret) {117		kfree(ctx);118		return ERR_PTR(ret);119	}120 121	return ctx;122}123 124static int zstd_init(struct crypto_tfm *tfm)125{126	struct zstd_ctx *ctx = crypto_tfm_ctx(tfm);127 128	return __zstd_init(ctx);129}130 131static void __zstd_exit(void *ctx)132{133	zstd_comp_exit(ctx);134	zstd_decomp_exit(ctx);135}136 137static void zstd_free_ctx(struct crypto_scomp *tfm, void *ctx)138{139	__zstd_exit(ctx);140	kfree_sensitive(ctx);141}142 143static void zstd_exit(struct crypto_tfm *tfm)144{145	struct zstd_ctx *ctx = crypto_tfm_ctx(tfm);146 147	__zstd_exit(ctx);148}149 150static int __zstd_compress(const u8 *src, unsigned int slen,151			   u8 *dst, unsigned int *dlen, void *ctx)152{153	size_t out_len;154	struct zstd_ctx *zctx = ctx;155	const zstd_parameters params = zstd_params();156 157	out_len = zstd_compress_cctx(zctx->cctx, dst, *dlen, src, slen, &params);158	if (zstd_is_error(out_len))159		return -EINVAL;160	*dlen = out_len;161	return 0;162}163 164static int zstd_compress(struct crypto_tfm *tfm, const u8 *src,165			 unsigned int slen, u8 *dst, unsigned int *dlen)166{167	struct zstd_ctx *ctx = crypto_tfm_ctx(tfm);168 169	return __zstd_compress(src, slen, dst, dlen, ctx);170}171 172static int zstd_scompress(struct crypto_scomp *tfm, const u8 *src,173			  unsigned int slen, u8 *dst, unsigned int *dlen,174			  void *ctx)175{176	return __zstd_compress(src, slen, dst, dlen, ctx);177}178 179static int __zstd_decompress(const u8 *src, unsigned int slen,180			     u8 *dst, unsigned int *dlen, void *ctx)181{182	size_t out_len;183	struct zstd_ctx *zctx = ctx;184 185	out_len = zstd_decompress_dctx(zctx->dctx, dst, *dlen, src, slen);186	if (zstd_is_error(out_len))187		return -EINVAL;188	*dlen = out_len;189	return 0;190}191 192static int zstd_decompress(struct crypto_tfm *tfm, const u8 *src,193			   unsigned int slen, u8 *dst, unsigned int *dlen)194{195	struct zstd_ctx *ctx = crypto_tfm_ctx(tfm);196 197	return __zstd_decompress(src, slen, dst, dlen, ctx);198}199 200static int zstd_sdecompress(struct crypto_scomp *tfm, const u8 *src,201			    unsigned int slen, u8 *dst, unsigned int *dlen,202			    void *ctx)203{204	return __zstd_decompress(src, slen, dst, dlen, ctx);205}206 207static struct crypto_alg alg = {208	.cra_name		= "zstd",209	.cra_driver_name	= "zstd-generic",210	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,211	.cra_ctxsize		= sizeof(struct zstd_ctx),212	.cra_module		= THIS_MODULE,213	.cra_init		= zstd_init,214	.cra_exit		= zstd_exit,215	.cra_u			= { .compress = {216	.coa_compress		= zstd_compress,217	.coa_decompress		= zstd_decompress } }218};219 220static struct scomp_alg scomp = {221	.alloc_ctx		= zstd_alloc_ctx,222	.free_ctx		= zstd_free_ctx,223	.compress		= zstd_scompress,224	.decompress		= zstd_sdecompress,225	.base			= {226		.cra_name	= "zstd",227		.cra_driver_name = "zstd-scomp",228		.cra_module	 = THIS_MODULE,229	}230};231 232static int __init zstd_mod_init(void)233{234	int ret;235 236	ret = crypto_register_alg(&alg);237	if (ret)238		return ret;239 240	ret = crypto_register_scomp(&scomp);241	if (ret)242		crypto_unregister_alg(&alg);243 244	return ret;245}246 247static void __exit zstd_mod_fini(void)248{249	crypto_unregister_alg(&alg);250	crypto_unregister_scomp(&scomp);251}252 253subsys_initcall(zstd_mod_init);254module_exit(zstd_mod_fini);255 256MODULE_LICENSE("GPL");257MODULE_DESCRIPTION("Zstd Compression Algorithm");258MODULE_ALIAS_CRYPTO("zstd");259