xref: /linux/crypto/lz4hc.c (revision 91d53d96e27018d4f49b9e5994cc1e74a4fc5d92)
10ea8530dSChanho Min /*
20ea8530dSChanho Min  * Cryptographic API.
30ea8530dSChanho Min  *
40ea8530dSChanho Min  * Copyright (c) 2013 Chanho Min <chanho.min@lge.com>
50ea8530dSChanho Min  *
60ea8530dSChanho Min  * This program is free software; you can redistribute it and/or modify it
70ea8530dSChanho Min  * under the terms of the GNU General Public License version 2 as published by
80ea8530dSChanho Min  * the Free Software Foundation.
90ea8530dSChanho Min  *
100ea8530dSChanho Min  * This program is distributed in the hope that it will be useful, but WITHOUT
110ea8530dSChanho Min  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
120ea8530dSChanho Min  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
130ea8530dSChanho Min  * more details.
140ea8530dSChanho Min  *
150ea8530dSChanho Min  * You should have received a copy of the GNU General Public License along with
160ea8530dSChanho Min  * this program; if not, write to the Free Software Foundation, Inc., 51
170ea8530dSChanho Min  * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
180ea8530dSChanho Min  *
190ea8530dSChanho Min  */
200ea8530dSChanho Min #include <linux/init.h>
210ea8530dSChanho Min #include <linux/module.h>
220ea8530dSChanho Min #include <linux/crypto.h>
230ea8530dSChanho Min #include <linux/vmalloc.h>
240ea8530dSChanho Min #include <linux/lz4.h>
25*91d53d96SGiovanni Cabiddu #include <crypto/internal/scompress.h>
260ea8530dSChanho Min 
270ea8530dSChanho Min struct lz4hc_ctx {
280ea8530dSChanho Min 	void *lz4hc_comp_mem;
290ea8530dSChanho Min };
300ea8530dSChanho Min 
31*91d53d96SGiovanni Cabiddu static void *lz4hc_alloc_ctx(struct crypto_scomp *tfm)
32*91d53d96SGiovanni Cabiddu {
33*91d53d96SGiovanni Cabiddu 	void *ctx;
34*91d53d96SGiovanni Cabiddu 
35*91d53d96SGiovanni Cabiddu 	ctx = vmalloc(LZ4HC_MEM_COMPRESS);
36*91d53d96SGiovanni Cabiddu 	if (!ctx)
37*91d53d96SGiovanni Cabiddu 		return ERR_PTR(-ENOMEM);
38*91d53d96SGiovanni Cabiddu 
39*91d53d96SGiovanni Cabiddu 	return ctx;
40*91d53d96SGiovanni Cabiddu }
41*91d53d96SGiovanni Cabiddu 
420ea8530dSChanho Min static int lz4hc_init(struct crypto_tfm *tfm)
430ea8530dSChanho Min {
440ea8530dSChanho Min 	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
450ea8530dSChanho Min 
46*91d53d96SGiovanni Cabiddu 	ctx->lz4hc_comp_mem = lz4hc_alloc_ctx(NULL);
47*91d53d96SGiovanni Cabiddu 	if (IS_ERR(ctx->lz4hc_comp_mem))
480ea8530dSChanho Min 		return -ENOMEM;
490ea8530dSChanho Min 
500ea8530dSChanho Min 	return 0;
510ea8530dSChanho Min }
520ea8530dSChanho Min 
53*91d53d96SGiovanni Cabiddu static void lz4hc_free_ctx(struct crypto_scomp *tfm, void *ctx)
54*91d53d96SGiovanni Cabiddu {
55*91d53d96SGiovanni Cabiddu 	vfree(ctx);
56*91d53d96SGiovanni Cabiddu }
57*91d53d96SGiovanni Cabiddu 
580ea8530dSChanho Min static void lz4hc_exit(struct crypto_tfm *tfm)
590ea8530dSChanho Min {
600ea8530dSChanho Min 	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
610ea8530dSChanho Min 
62*91d53d96SGiovanni Cabiddu 	lz4hc_free_ctx(NULL, ctx->lz4hc_comp_mem);
630ea8530dSChanho Min }
640ea8530dSChanho Min 
65*91d53d96SGiovanni Cabiddu static int __lz4hc_compress_crypto(const u8 *src, unsigned int slen,
66*91d53d96SGiovanni Cabiddu 				   u8 *dst, unsigned int *dlen, void *ctx)
670ea8530dSChanho Min {
680ea8530dSChanho Min 	size_t tmp_len = *dlen;
690ea8530dSChanho Min 	int err;
700ea8530dSChanho Min 
71*91d53d96SGiovanni Cabiddu 	err = lz4hc_compress(src, slen, dst, &tmp_len, ctx);
720ea8530dSChanho Min 
730ea8530dSChanho Min 	if (err < 0)
740ea8530dSChanho Min 		return -EINVAL;
750ea8530dSChanho Min 
760ea8530dSChanho Min 	*dlen = tmp_len;
770ea8530dSChanho Min 	return 0;
780ea8530dSChanho Min }
790ea8530dSChanho Min 
80*91d53d96SGiovanni Cabiddu static int lz4hc_scompress(struct crypto_scomp *tfm, const u8 *src,
81*91d53d96SGiovanni Cabiddu 			   unsigned int slen, u8 *dst, unsigned int *dlen,
82*91d53d96SGiovanni Cabiddu 			   void *ctx)
83*91d53d96SGiovanni Cabiddu {
84*91d53d96SGiovanni Cabiddu 	return __lz4hc_compress_crypto(src, slen, dst, dlen, ctx);
85*91d53d96SGiovanni Cabiddu }
86*91d53d96SGiovanni Cabiddu 
87*91d53d96SGiovanni Cabiddu static int lz4hc_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
88*91d53d96SGiovanni Cabiddu 				 unsigned int slen, u8 *dst,
89*91d53d96SGiovanni Cabiddu 				 unsigned int *dlen)
90*91d53d96SGiovanni Cabiddu {
91*91d53d96SGiovanni Cabiddu 	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
92*91d53d96SGiovanni Cabiddu 
93*91d53d96SGiovanni Cabiddu 	return __lz4hc_compress_crypto(src, slen, dst, dlen,
94*91d53d96SGiovanni Cabiddu 					ctx->lz4hc_comp_mem);
95*91d53d96SGiovanni Cabiddu }
96*91d53d96SGiovanni Cabiddu 
97*91d53d96SGiovanni Cabiddu static int __lz4hc_decompress_crypto(const u8 *src, unsigned int slen,
98*91d53d96SGiovanni Cabiddu 				     u8 *dst, unsigned int *dlen, void *ctx)
990ea8530dSChanho Min {
1000ea8530dSChanho Min 	int err;
1010ea8530dSChanho Min 	size_t tmp_len = *dlen;
1020ea8530dSChanho Min 	size_t __slen = slen;
1030ea8530dSChanho Min 
104d801ab20SKOVACS Krisztian 	err = lz4_decompress_unknownoutputsize(src, __slen, dst, &tmp_len);
1050ea8530dSChanho Min 	if (err < 0)
1060ea8530dSChanho Min 		return -EINVAL;
1070ea8530dSChanho Min 
1080ea8530dSChanho Min 	*dlen = tmp_len;
1090ea8530dSChanho Min 	return err;
1100ea8530dSChanho Min }
1110ea8530dSChanho Min 
112*91d53d96SGiovanni Cabiddu static int lz4hc_sdecompress(struct crypto_scomp *tfm, const u8 *src,
113*91d53d96SGiovanni Cabiddu 			     unsigned int slen, u8 *dst, unsigned int *dlen,
114*91d53d96SGiovanni Cabiddu 			     void *ctx)
115*91d53d96SGiovanni Cabiddu {
116*91d53d96SGiovanni Cabiddu 	return __lz4hc_decompress_crypto(src, slen, dst, dlen, NULL);
117*91d53d96SGiovanni Cabiddu }
118*91d53d96SGiovanni Cabiddu 
119*91d53d96SGiovanni Cabiddu static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
120*91d53d96SGiovanni Cabiddu 				   unsigned int slen, u8 *dst,
121*91d53d96SGiovanni Cabiddu 				   unsigned int *dlen)
122*91d53d96SGiovanni Cabiddu {
123*91d53d96SGiovanni Cabiddu 	return __lz4hc_decompress_crypto(src, slen, dst, dlen, NULL);
124*91d53d96SGiovanni Cabiddu }
125*91d53d96SGiovanni Cabiddu 
1260ea8530dSChanho Min static struct crypto_alg alg_lz4hc = {
1270ea8530dSChanho Min 	.cra_name		= "lz4hc",
1280ea8530dSChanho Min 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
1290ea8530dSChanho Min 	.cra_ctxsize		= sizeof(struct lz4hc_ctx),
1300ea8530dSChanho Min 	.cra_module		= THIS_MODULE,
1310ea8530dSChanho Min 	.cra_list		= LIST_HEAD_INIT(alg_lz4hc.cra_list),
1320ea8530dSChanho Min 	.cra_init		= lz4hc_init,
1330ea8530dSChanho Min 	.cra_exit		= lz4hc_exit,
1340ea8530dSChanho Min 	.cra_u			= { .compress = {
1350ea8530dSChanho Min 	.coa_compress		= lz4hc_compress_crypto,
1360ea8530dSChanho Min 	.coa_decompress		= lz4hc_decompress_crypto } }
1370ea8530dSChanho Min };
1380ea8530dSChanho Min 
139*91d53d96SGiovanni Cabiddu static struct scomp_alg scomp = {
140*91d53d96SGiovanni Cabiddu 	.alloc_ctx		= lz4hc_alloc_ctx,
141*91d53d96SGiovanni Cabiddu 	.free_ctx		= lz4hc_free_ctx,
142*91d53d96SGiovanni Cabiddu 	.compress		= lz4hc_scompress,
143*91d53d96SGiovanni Cabiddu 	.decompress		= lz4hc_sdecompress,
144*91d53d96SGiovanni Cabiddu 	.base			= {
145*91d53d96SGiovanni Cabiddu 		.cra_name	= "lz4hc",
146*91d53d96SGiovanni Cabiddu 		.cra_driver_name = "lz4hc-scomp",
147*91d53d96SGiovanni Cabiddu 		.cra_module	 = THIS_MODULE,
148*91d53d96SGiovanni Cabiddu 	}
149*91d53d96SGiovanni Cabiddu };
150*91d53d96SGiovanni Cabiddu 
1510ea8530dSChanho Min static int __init lz4hc_mod_init(void)
1520ea8530dSChanho Min {
153*91d53d96SGiovanni Cabiddu 	int ret;
154*91d53d96SGiovanni Cabiddu 
155*91d53d96SGiovanni Cabiddu 	ret = crypto_register_alg(&alg_lz4hc);
156*91d53d96SGiovanni Cabiddu 	if (ret)
157*91d53d96SGiovanni Cabiddu 		return ret;
158*91d53d96SGiovanni Cabiddu 
159*91d53d96SGiovanni Cabiddu 	ret = crypto_register_scomp(&scomp);
160*91d53d96SGiovanni Cabiddu 	if (ret) {
161*91d53d96SGiovanni Cabiddu 		crypto_unregister_alg(&alg_lz4hc);
162*91d53d96SGiovanni Cabiddu 		return ret;
163*91d53d96SGiovanni Cabiddu 	}
164*91d53d96SGiovanni Cabiddu 
165*91d53d96SGiovanni Cabiddu 	return ret;
1660ea8530dSChanho Min }
1670ea8530dSChanho Min 
1680ea8530dSChanho Min static void __exit lz4hc_mod_fini(void)
1690ea8530dSChanho Min {
1700ea8530dSChanho Min 	crypto_unregister_alg(&alg_lz4hc);
171*91d53d96SGiovanni Cabiddu 	crypto_unregister_scomp(&scomp);
1720ea8530dSChanho Min }
1730ea8530dSChanho Min 
1740ea8530dSChanho Min module_init(lz4hc_mod_init);
1750ea8530dSChanho Min module_exit(lz4hc_mod_fini);
1760ea8530dSChanho Min 
1770ea8530dSChanho Min MODULE_LICENSE("GPL");
1780ea8530dSChanho Min MODULE_DESCRIPTION("LZ4HC Compression Algorithm");
1795d26a105SKees Cook MODULE_ALIAS_CRYPTO("lz4hc");
180