xref: /linux/crypto/lz4.c (revision 0898782247ae533d1f4e47a06bc5d4870931b284)
12b27bdccSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20ea8530dSChanho Min /*
30ea8530dSChanho Min  * Cryptographic API.
40ea8530dSChanho Min  *
50ea8530dSChanho Min  * Copyright (c) 2013 Chanho Min <chanho.min@lge.com>
60ea8530dSChanho Min  */
70ea8530dSChanho Min 
80ea8530dSChanho Min #include <linux/init.h>
90ea8530dSChanho Min #include <linux/module.h>
100ea8530dSChanho Min #include <linux/crypto.h>
110ea8530dSChanho Min #include <linux/vmalloc.h>
120ea8530dSChanho Min #include <linux/lz4.h>
138cd9330eSGiovanni Cabiddu #include <crypto/internal/scompress.h>
140ea8530dSChanho Min 
150ea8530dSChanho Min struct lz4_ctx {
160ea8530dSChanho Min 	void *lz4_comp_mem;
170ea8530dSChanho Min };
180ea8530dSChanho Min 
lz4_alloc_ctx(struct crypto_scomp * tfm)198cd9330eSGiovanni Cabiddu static void *lz4_alloc_ctx(struct crypto_scomp *tfm)
208cd9330eSGiovanni Cabiddu {
218cd9330eSGiovanni Cabiddu 	void *ctx;
228cd9330eSGiovanni Cabiddu 
238cd9330eSGiovanni Cabiddu 	ctx = vmalloc(LZ4_MEM_COMPRESS);
248cd9330eSGiovanni Cabiddu 	if (!ctx)
258cd9330eSGiovanni Cabiddu 		return ERR_PTR(-ENOMEM);
268cd9330eSGiovanni Cabiddu 
278cd9330eSGiovanni Cabiddu 	return ctx;
288cd9330eSGiovanni Cabiddu }
298cd9330eSGiovanni Cabiddu 
lz4_init(struct crypto_tfm * tfm)300ea8530dSChanho Min static int lz4_init(struct crypto_tfm *tfm)
310ea8530dSChanho Min {
320ea8530dSChanho Min 	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
330ea8530dSChanho Min 
348cd9330eSGiovanni Cabiddu 	ctx->lz4_comp_mem = lz4_alloc_ctx(NULL);
358cd9330eSGiovanni Cabiddu 	if (IS_ERR(ctx->lz4_comp_mem))
360ea8530dSChanho Min 		return -ENOMEM;
370ea8530dSChanho Min 
380ea8530dSChanho Min 	return 0;
390ea8530dSChanho Min }
400ea8530dSChanho Min 
lz4_free_ctx(struct crypto_scomp * tfm,void * ctx)418cd9330eSGiovanni Cabiddu static void lz4_free_ctx(struct crypto_scomp *tfm, void *ctx)
428cd9330eSGiovanni Cabiddu {
438cd9330eSGiovanni Cabiddu 	vfree(ctx);
448cd9330eSGiovanni Cabiddu }
458cd9330eSGiovanni Cabiddu 
lz4_exit(struct crypto_tfm * tfm)460ea8530dSChanho Min static void lz4_exit(struct crypto_tfm *tfm)
470ea8530dSChanho Min {
480ea8530dSChanho Min 	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
498cd9330eSGiovanni Cabiddu 
508cd9330eSGiovanni Cabiddu 	lz4_free_ctx(NULL, ctx->lz4_comp_mem);
510ea8530dSChanho Min }
520ea8530dSChanho Min 
__lz4_compress_crypto(const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen,void * ctx)538cd9330eSGiovanni Cabiddu static int __lz4_compress_crypto(const u8 *src, unsigned int slen,
548cd9330eSGiovanni Cabiddu 				 u8 *dst, unsigned int *dlen, void *ctx)
550ea8530dSChanho Min {
5673a15ac6SSven Schmidt 	int out_len = LZ4_compress_default(src, dst,
5773a15ac6SSven Schmidt 		slen, *dlen, ctx);
580ea8530dSChanho Min 
5973a15ac6SSven Schmidt 	if (!out_len)
600ea8530dSChanho Min 		return -EINVAL;
610ea8530dSChanho Min 
6273a15ac6SSven Schmidt 	*dlen = out_len;
630ea8530dSChanho Min 	return 0;
640ea8530dSChanho Min }
650ea8530dSChanho Min 
lz4_scompress(struct crypto_scomp * tfm,const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen,void * ctx)668cd9330eSGiovanni Cabiddu static int lz4_scompress(struct crypto_scomp *tfm, const u8 *src,
678cd9330eSGiovanni Cabiddu 			 unsigned int slen, u8 *dst, unsigned int *dlen,
688cd9330eSGiovanni Cabiddu 			 void *ctx)
698cd9330eSGiovanni Cabiddu {
708cd9330eSGiovanni Cabiddu 	return __lz4_compress_crypto(src, slen, dst, dlen, ctx);
718cd9330eSGiovanni Cabiddu }
728cd9330eSGiovanni Cabiddu 
lz4_compress_crypto(struct crypto_tfm * tfm,const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen)738cd9330eSGiovanni Cabiddu static int lz4_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
740ea8530dSChanho Min 			       unsigned int slen, u8 *dst, unsigned int *dlen)
750ea8530dSChanho Min {
768cd9330eSGiovanni Cabiddu 	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
778cd9330eSGiovanni Cabiddu 
788cd9330eSGiovanni Cabiddu 	return __lz4_compress_crypto(src, slen, dst, dlen, ctx->lz4_comp_mem);
798cd9330eSGiovanni Cabiddu }
808cd9330eSGiovanni Cabiddu 
__lz4_decompress_crypto(const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen,void * ctx)818cd9330eSGiovanni Cabiddu static int __lz4_decompress_crypto(const u8 *src, unsigned int slen,
828cd9330eSGiovanni Cabiddu 				   u8 *dst, unsigned int *dlen, void *ctx)
838cd9330eSGiovanni Cabiddu {
8473a15ac6SSven Schmidt 	int out_len = LZ4_decompress_safe(src, dst, slen, *dlen);
850ea8530dSChanho Min 
8673a15ac6SSven Schmidt 	if (out_len < 0)
87cd15f102SMyungho Jung 		return -EINVAL;
880ea8530dSChanho Min 
8973a15ac6SSven Schmidt 	*dlen = out_len;
9073a15ac6SSven Schmidt 	return 0;
910ea8530dSChanho Min }
920ea8530dSChanho Min 
lz4_sdecompress(struct crypto_scomp * tfm,const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen,void * ctx)938cd9330eSGiovanni Cabiddu static int lz4_sdecompress(struct crypto_scomp *tfm, const u8 *src,
948cd9330eSGiovanni Cabiddu 			   unsigned int slen, u8 *dst, unsigned int *dlen,
958cd9330eSGiovanni Cabiddu 			   void *ctx)
968cd9330eSGiovanni Cabiddu {
978cd9330eSGiovanni Cabiddu 	return __lz4_decompress_crypto(src, slen, dst, dlen, NULL);
988cd9330eSGiovanni Cabiddu }
998cd9330eSGiovanni Cabiddu 
lz4_decompress_crypto(struct crypto_tfm * tfm,const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen)1008cd9330eSGiovanni Cabiddu static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
1018cd9330eSGiovanni Cabiddu 				 unsigned int slen, u8 *dst,
1028cd9330eSGiovanni Cabiddu 				 unsigned int *dlen)
1038cd9330eSGiovanni Cabiddu {
1048cd9330eSGiovanni Cabiddu 	return __lz4_decompress_crypto(src, slen, dst, dlen, NULL);
1058cd9330eSGiovanni Cabiddu }
1068cd9330eSGiovanni Cabiddu 
1070ea8530dSChanho Min static struct crypto_alg alg_lz4 = {
1080ea8530dSChanho Min 	.cra_name		= "lz4",
109*d6ebf528SEric Biggers 	.cra_driver_name	= "lz4-generic",
1100ea8530dSChanho Min 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
1110ea8530dSChanho Min 	.cra_ctxsize		= sizeof(struct lz4_ctx),
1120ea8530dSChanho Min 	.cra_module		= THIS_MODULE,
1130ea8530dSChanho Min 	.cra_init		= lz4_init,
1140ea8530dSChanho Min 	.cra_exit		= lz4_exit,
1150ea8530dSChanho Min 	.cra_u			= { .compress = {
1160ea8530dSChanho Min 	.coa_compress		= lz4_compress_crypto,
1170ea8530dSChanho Min 	.coa_decompress		= lz4_decompress_crypto } }
1180ea8530dSChanho Min };
1190ea8530dSChanho Min 
1208cd9330eSGiovanni Cabiddu static struct scomp_alg scomp = {
1218cd9330eSGiovanni Cabiddu 	.alloc_ctx		= lz4_alloc_ctx,
1228cd9330eSGiovanni Cabiddu 	.free_ctx		= lz4_free_ctx,
1238cd9330eSGiovanni Cabiddu 	.compress		= lz4_scompress,
1248cd9330eSGiovanni Cabiddu 	.decompress		= lz4_sdecompress,
1258cd9330eSGiovanni Cabiddu 	.base			= {
1268cd9330eSGiovanni Cabiddu 		.cra_name	= "lz4",
1278cd9330eSGiovanni Cabiddu 		.cra_driver_name = "lz4-scomp",
1288cd9330eSGiovanni Cabiddu 		.cra_module	 = THIS_MODULE,
1298cd9330eSGiovanni Cabiddu 	}
1308cd9330eSGiovanni Cabiddu };
1318cd9330eSGiovanni Cabiddu 
lz4_mod_init(void)1320ea8530dSChanho Min static int __init lz4_mod_init(void)
1330ea8530dSChanho Min {
1348cd9330eSGiovanni Cabiddu 	int ret;
1358cd9330eSGiovanni Cabiddu 
1368cd9330eSGiovanni Cabiddu 	ret = crypto_register_alg(&alg_lz4);
1378cd9330eSGiovanni Cabiddu 	if (ret)
1388cd9330eSGiovanni Cabiddu 		return ret;
1398cd9330eSGiovanni Cabiddu 
1408cd9330eSGiovanni Cabiddu 	ret = crypto_register_scomp(&scomp);
1418cd9330eSGiovanni Cabiddu 	if (ret) {
1428cd9330eSGiovanni Cabiddu 		crypto_unregister_alg(&alg_lz4);
1438cd9330eSGiovanni Cabiddu 		return ret;
1448cd9330eSGiovanni Cabiddu 	}
1458cd9330eSGiovanni Cabiddu 
1468cd9330eSGiovanni Cabiddu 	return ret;
1470ea8530dSChanho Min }
1480ea8530dSChanho Min 
lz4_mod_fini(void)1490ea8530dSChanho Min static void __exit lz4_mod_fini(void)
1500ea8530dSChanho Min {
1510ea8530dSChanho Min 	crypto_unregister_alg(&alg_lz4);
1528cd9330eSGiovanni Cabiddu 	crypto_unregister_scomp(&scomp);
1530ea8530dSChanho Min }
1540ea8530dSChanho Min 
155c4741b23SEric Biggers subsys_initcall(lz4_mod_init);
1560ea8530dSChanho Min module_exit(lz4_mod_fini);
1570ea8530dSChanho Min 
1580ea8530dSChanho Min MODULE_LICENSE("GPL");
1590ea8530dSChanho Min MODULE_DESCRIPTION("LZ4 Compression Algorithm");
1605d26a105SKees Cook MODULE_ALIAS_CRYPTO("lz4");
161