xref: /linux/crypto/lz4hc.c (revision 73a15ac6d5413caaee95979e318df58d4ee6d9a3)
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>
2591d53d96SGiovanni Cabiddu #include <crypto/internal/scompress.h>
260ea8530dSChanho Min 
270ea8530dSChanho Min struct lz4hc_ctx {
280ea8530dSChanho Min 	void *lz4hc_comp_mem;
290ea8530dSChanho Min };
300ea8530dSChanho Min 
3191d53d96SGiovanni Cabiddu static void *lz4hc_alloc_ctx(struct crypto_scomp *tfm)
3291d53d96SGiovanni Cabiddu {
3391d53d96SGiovanni Cabiddu 	void *ctx;
3491d53d96SGiovanni Cabiddu 
3591d53d96SGiovanni Cabiddu 	ctx = vmalloc(LZ4HC_MEM_COMPRESS);
3691d53d96SGiovanni Cabiddu 	if (!ctx)
3791d53d96SGiovanni Cabiddu 		return ERR_PTR(-ENOMEM);
3891d53d96SGiovanni Cabiddu 
3991d53d96SGiovanni Cabiddu 	return ctx;
4091d53d96SGiovanni Cabiddu }
4191d53d96SGiovanni 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 
4691d53d96SGiovanni Cabiddu 	ctx->lz4hc_comp_mem = lz4hc_alloc_ctx(NULL);
4791d53d96SGiovanni Cabiddu 	if (IS_ERR(ctx->lz4hc_comp_mem))
480ea8530dSChanho Min 		return -ENOMEM;
490ea8530dSChanho Min 
500ea8530dSChanho Min 	return 0;
510ea8530dSChanho Min }
520ea8530dSChanho Min 
5391d53d96SGiovanni Cabiddu static void lz4hc_free_ctx(struct crypto_scomp *tfm, void *ctx)
5491d53d96SGiovanni Cabiddu {
5591d53d96SGiovanni Cabiddu 	vfree(ctx);
5691d53d96SGiovanni Cabiddu }
5791d53d96SGiovanni 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 
6291d53d96SGiovanni Cabiddu 	lz4hc_free_ctx(NULL, ctx->lz4hc_comp_mem);
630ea8530dSChanho Min }
640ea8530dSChanho Min 
6591d53d96SGiovanni Cabiddu static int __lz4hc_compress_crypto(const u8 *src, unsigned int slen,
6691d53d96SGiovanni Cabiddu 				   u8 *dst, unsigned int *dlen, void *ctx)
670ea8530dSChanho Min {
68*73a15ac6SSven Schmidt 	int out_len = LZ4_compress_HC(src, dst, slen,
69*73a15ac6SSven Schmidt 		*dlen, LZ4HC_DEFAULT_CLEVEL, ctx);
700ea8530dSChanho Min 
71*73a15ac6SSven Schmidt 	if (!out_len)
720ea8530dSChanho Min 		return -EINVAL;
730ea8530dSChanho Min 
74*73a15ac6SSven Schmidt 	*dlen = out_len;
750ea8530dSChanho Min 	return 0;
760ea8530dSChanho Min }
770ea8530dSChanho Min 
7891d53d96SGiovanni Cabiddu static int lz4hc_scompress(struct crypto_scomp *tfm, const u8 *src,
7991d53d96SGiovanni Cabiddu 			   unsigned int slen, u8 *dst, unsigned int *dlen,
8091d53d96SGiovanni Cabiddu 			   void *ctx)
8191d53d96SGiovanni Cabiddu {
8291d53d96SGiovanni Cabiddu 	return __lz4hc_compress_crypto(src, slen, dst, dlen, ctx);
8391d53d96SGiovanni Cabiddu }
8491d53d96SGiovanni Cabiddu 
8591d53d96SGiovanni Cabiddu static int lz4hc_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
8691d53d96SGiovanni Cabiddu 				 unsigned int slen, u8 *dst,
8791d53d96SGiovanni Cabiddu 				 unsigned int *dlen)
8891d53d96SGiovanni Cabiddu {
8991d53d96SGiovanni Cabiddu 	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
9091d53d96SGiovanni Cabiddu 
9191d53d96SGiovanni Cabiddu 	return __lz4hc_compress_crypto(src, slen, dst, dlen,
9291d53d96SGiovanni Cabiddu 					ctx->lz4hc_comp_mem);
9391d53d96SGiovanni Cabiddu }
9491d53d96SGiovanni Cabiddu 
9591d53d96SGiovanni Cabiddu static int __lz4hc_decompress_crypto(const u8 *src, unsigned int slen,
9691d53d96SGiovanni Cabiddu 				     u8 *dst, unsigned int *dlen, void *ctx)
970ea8530dSChanho Min {
98*73a15ac6SSven Schmidt 	int out_len = LZ4_decompress_safe(src, dst, slen, *dlen);
990ea8530dSChanho Min 
100*73a15ac6SSven Schmidt 	if (out_len < 0)
101*73a15ac6SSven Schmidt 		return out_len;
1020ea8530dSChanho Min 
103*73a15ac6SSven Schmidt 	*dlen = out_len;
104*73a15ac6SSven Schmidt 	return 0;
1050ea8530dSChanho Min }
1060ea8530dSChanho Min 
10791d53d96SGiovanni Cabiddu static int lz4hc_sdecompress(struct crypto_scomp *tfm, const u8 *src,
10891d53d96SGiovanni Cabiddu 			     unsigned int slen, u8 *dst, unsigned int *dlen,
10991d53d96SGiovanni Cabiddu 			     void *ctx)
11091d53d96SGiovanni Cabiddu {
11191d53d96SGiovanni Cabiddu 	return __lz4hc_decompress_crypto(src, slen, dst, dlen, NULL);
11291d53d96SGiovanni Cabiddu }
11391d53d96SGiovanni Cabiddu 
11491d53d96SGiovanni Cabiddu static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
11591d53d96SGiovanni Cabiddu 				   unsigned int slen, u8 *dst,
11691d53d96SGiovanni Cabiddu 				   unsigned int *dlen)
11791d53d96SGiovanni Cabiddu {
11891d53d96SGiovanni Cabiddu 	return __lz4hc_decompress_crypto(src, slen, dst, dlen, NULL);
11991d53d96SGiovanni Cabiddu }
12091d53d96SGiovanni Cabiddu 
1210ea8530dSChanho Min static struct crypto_alg alg_lz4hc = {
1220ea8530dSChanho Min 	.cra_name		= "lz4hc",
1230ea8530dSChanho Min 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
1240ea8530dSChanho Min 	.cra_ctxsize		= sizeof(struct lz4hc_ctx),
1250ea8530dSChanho Min 	.cra_module		= THIS_MODULE,
1260ea8530dSChanho Min 	.cra_list		= LIST_HEAD_INIT(alg_lz4hc.cra_list),
1270ea8530dSChanho Min 	.cra_init		= lz4hc_init,
1280ea8530dSChanho Min 	.cra_exit		= lz4hc_exit,
1290ea8530dSChanho Min 	.cra_u			= { .compress = {
1300ea8530dSChanho Min 	.coa_compress		= lz4hc_compress_crypto,
1310ea8530dSChanho Min 	.coa_decompress		= lz4hc_decompress_crypto } }
1320ea8530dSChanho Min };
1330ea8530dSChanho Min 
13491d53d96SGiovanni Cabiddu static struct scomp_alg scomp = {
13591d53d96SGiovanni Cabiddu 	.alloc_ctx		= lz4hc_alloc_ctx,
13691d53d96SGiovanni Cabiddu 	.free_ctx		= lz4hc_free_ctx,
13791d53d96SGiovanni Cabiddu 	.compress		= lz4hc_scompress,
13891d53d96SGiovanni Cabiddu 	.decompress		= lz4hc_sdecompress,
13991d53d96SGiovanni Cabiddu 	.base			= {
14091d53d96SGiovanni Cabiddu 		.cra_name	= "lz4hc",
14191d53d96SGiovanni Cabiddu 		.cra_driver_name = "lz4hc-scomp",
14291d53d96SGiovanni Cabiddu 		.cra_module	 = THIS_MODULE,
14391d53d96SGiovanni Cabiddu 	}
14491d53d96SGiovanni Cabiddu };
14591d53d96SGiovanni Cabiddu 
1460ea8530dSChanho Min static int __init lz4hc_mod_init(void)
1470ea8530dSChanho Min {
14891d53d96SGiovanni Cabiddu 	int ret;
14991d53d96SGiovanni Cabiddu 
15091d53d96SGiovanni Cabiddu 	ret = crypto_register_alg(&alg_lz4hc);
15191d53d96SGiovanni Cabiddu 	if (ret)
15291d53d96SGiovanni Cabiddu 		return ret;
15391d53d96SGiovanni Cabiddu 
15491d53d96SGiovanni Cabiddu 	ret = crypto_register_scomp(&scomp);
15591d53d96SGiovanni Cabiddu 	if (ret) {
15691d53d96SGiovanni Cabiddu 		crypto_unregister_alg(&alg_lz4hc);
15791d53d96SGiovanni Cabiddu 		return ret;
15891d53d96SGiovanni Cabiddu 	}
15991d53d96SGiovanni Cabiddu 
16091d53d96SGiovanni Cabiddu 	return ret;
1610ea8530dSChanho Min }
1620ea8530dSChanho Min 
1630ea8530dSChanho Min static void __exit lz4hc_mod_fini(void)
1640ea8530dSChanho Min {
1650ea8530dSChanho Min 	crypto_unregister_alg(&alg_lz4hc);
16691d53d96SGiovanni Cabiddu 	crypto_unregister_scomp(&scomp);
1670ea8530dSChanho Min }
1680ea8530dSChanho Min 
1690ea8530dSChanho Min module_init(lz4hc_mod_init);
1700ea8530dSChanho Min module_exit(lz4hc_mod_fini);
1710ea8530dSChanho Min 
1720ea8530dSChanho Min MODULE_LICENSE("GPL");
1730ea8530dSChanho Min MODULE_DESCRIPTION("LZ4HC Compression Algorithm");
1745d26a105SKees Cook MODULE_ALIAS_CRYPTO("lz4hc");
175