xref: /linux/crypto/lzo.c (revision 0898782247ae533d1f4e47a06bc5d4870931b284)
12b27bdccSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20b77abb3SZoltan Sogor /*
30b77abb3SZoltan Sogor  * Cryptographic API.
40b77abb3SZoltan Sogor  */
50b77abb3SZoltan Sogor 
60b77abb3SZoltan Sogor #include <linux/init.h>
70b77abb3SZoltan Sogor #include <linux/module.h>
80b77abb3SZoltan Sogor #include <linux/crypto.h>
90b77abb3SZoltan Sogor #include <linux/vmalloc.h>
1042614b05SEric Dumazet #include <linux/mm.h>
110b77abb3SZoltan Sogor #include <linux/lzo.h>
12ac9d2c4bSGiovanni Cabiddu #include <crypto/internal/scompress.h>
130b77abb3SZoltan Sogor 
140b77abb3SZoltan Sogor struct lzo_ctx {
150b77abb3SZoltan Sogor 	void *lzo_comp_mem;
160b77abb3SZoltan Sogor };
170b77abb3SZoltan Sogor 
lzo_alloc_ctx(struct crypto_scomp * tfm)18ac9d2c4bSGiovanni Cabiddu static void *lzo_alloc_ctx(struct crypto_scomp *tfm)
19ac9d2c4bSGiovanni Cabiddu {
20ac9d2c4bSGiovanni Cabiddu 	void *ctx;
21ac9d2c4bSGiovanni Cabiddu 
22752ade68SMichal Hocko 	ctx = kvmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
23ac9d2c4bSGiovanni Cabiddu 	if (!ctx)
24ac9d2c4bSGiovanni Cabiddu 		return ERR_PTR(-ENOMEM);
25ac9d2c4bSGiovanni Cabiddu 
26ac9d2c4bSGiovanni Cabiddu 	return ctx;
27ac9d2c4bSGiovanni Cabiddu }
28ac9d2c4bSGiovanni Cabiddu 
lzo_init(struct crypto_tfm * tfm)290b77abb3SZoltan Sogor static int lzo_init(struct crypto_tfm *tfm)
300b77abb3SZoltan Sogor {
310b77abb3SZoltan Sogor 	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
320b77abb3SZoltan Sogor 
33ac9d2c4bSGiovanni Cabiddu 	ctx->lzo_comp_mem = lzo_alloc_ctx(NULL);
34ac9d2c4bSGiovanni Cabiddu 	if (IS_ERR(ctx->lzo_comp_mem))
350b77abb3SZoltan Sogor 		return -ENOMEM;
360b77abb3SZoltan Sogor 
370b77abb3SZoltan Sogor 	return 0;
380b77abb3SZoltan Sogor }
390b77abb3SZoltan Sogor 
lzo_free_ctx(struct crypto_scomp * tfm,void * ctx)40ac9d2c4bSGiovanni Cabiddu static void lzo_free_ctx(struct crypto_scomp *tfm, void *ctx)
41ac9d2c4bSGiovanni Cabiddu {
42ac9d2c4bSGiovanni Cabiddu 	kvfree(ctx);
43ac9d2c4bSGiovanni Cabiddu }
44ac9d2c4bSGiovanni Cabiddu 
lzo_exit(struct crypto_tfm * tfm)450b77abb3SZoltan Sogor static void lzo_exit(struct crypto_tfm *tfm)
460b77abb3SZoltan Sogor {
470b77abb3SZoltan Sogor 	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
480b77abb3SZoltan Sogor 
49ac9d2c4bSGiovanni Cabiddu 	lzo_free_ctx(NULL, ctx->lzo_comp_mem);
500b77abb3SZoltan Sogor }
510b77abb3SZoltan Sogor 
__lzo_compress(const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen,void * ctx)52ac9d2c4bSGiovanni Cabiddu static int __lzo_compress(const u8 *src, unsigned int slen,
53ac9d2c4bSGiovanni Cabiddu 			  u8 *dst, unsigned int *dlen, void *ctx)
540b77abb3SZoltan Sogor {
550b77abb3SZoltan Sogor 	size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
560b77abb3SZoltan Sogor 	int err;
570b77abb3SZoltan Sogor 
58ac9d2c4bSGiovanni Cabiddu 	err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx);
590b77abb3SZoltan Sogor 
600b77abb3SZoltan Sogor 	if (err != LZO_E_OK)
610b77abb3SZoltan Sogor 		return -EINVAL;
620b77abb3SZoltan Sogor 
630b77abb3SZoltan Sogor 	*dlen = tmp_len;
640b77abb3SZoltan Sogor 	return 0;
650b77abb3SZoltan Sogor }
660b77abb3SZoltan Sogor 
lzo_compress(struct crypto_tfm * tfm,const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen)67ac9d2c4bSGiovanni Cabiddu static int lzo_compress(struct crypto_tfm *tfm, const u8 *src,
680b77abb3SZoltan Sogor 			unsigned int slen, u8 *dst, unsigned int *dlen)
690b77abb3SZoltan Sogor {
70ac9d2c4bSGiovanni Cabiddu 	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
71ac9d2c4bSGiovanni Cabiddu 
72ac9d2c4bSGiovanni Cabiddu 	return __lzo_compress(src, slen, dst, dlen, ctx->lzo_comp_mem);
73ac9d2c4bSGiovanni Cabiddu }
74ac9d2c4bSGiovanni Cabiddu 
lzo_scompress(struct crypto_scomp * tfm,const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen,void * ctx)75ac9d2c4bSGiovanni Cabiddu static int lzo_scompress(struct crypto_scomp *tfm, const u8 *src,
76ac9d2c4bSGiovanni Cabiddu 			 unsigned int slen, u8 *dst, unsigned int *dlen,
77ac9d2c4bSGiovanni Cabiddu 			 void *ctx)
78ac9d2c4bSGiovanni Cabiddu {
79ac9d2c4bSGiovanni Cabiddu 	return __lzo_compress(src, slen, dst, dlen, ctx);
80ac9d2c4bSGiovanni Cabiddu }
81ac9d2c4bSGiovanni Cabiddu 
__lzo_decompress(const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen)82ac9d2c4bSGiovanni Cabiddu static int __lzo_decompress(const u8 *src, unsigned int slen,
83ac9d2c4bSGiovanni Cabiddu 			    u8 *dst, unsigned int *dlen)
84ac9d2c4bSGiovanni Cabiddu {
850b77abb3SZoltan Sogor 	int err;
860b77abb3SZoltan Sogor 	size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
870b77abb3SZoltan Sogor 
880b77abb3SZoltan Sogor 	err = lzo1x_decompress_safe(src, slen, dst, &tmp_len);
890b77abb3SZoltan Sogor 
900b77abb3SZoltan Sogor 	if (err != LZO_E_OK)
910b77abb3SZoltan Sogor 		return -EINVAL;
920b77abb3SZoltan Sogor 
930b77abb3SZoltan Sogor 	*dlen = tmp_len;
940b77abb3SZoltan Sogor 	return 0;
95ac9d2c4bSGiovanni Cabiddu }
960b77abb3SZoltan Sogor 
lzo_decompress(struct crypto_tfm * tfm,const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen)97ac9d2c4bSGiovanni Cabiddu static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src,
98ac9d2c4bSGiovanni Cabiddu 			  unsigned int slen, u8 *dst, unsigned int *dlen)
99ac9d2c4bSGiovanni Cabiddu {
100ac9d2c4bSGiovanni Cabiddu 	return __lzo_decompress(src, slen, dst, dlen);
101ac9d2c4bSGiovanni Cabiddu }
102ac9d2c4bSGiovanni Cabiddu 
lzo_sdecompress(struct crypto_scomp * tfm,const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen,void * ctx)103ac9d2c4bSGiovanni Cabiddu static int lzo_sdecompress(struct crypto_scomp *tfm, const u8 *src,
104ac9d2c4bSGiovanni Cabiddu 			   unsigned int slen, u8 *dst, unsigned int *dlen,
105ac9d2c4bSGiovanni Cabiddu 			   void *ctx)
106ac9d2c4bSGiovanni Cabiddu {
107ac9d2c4bSGiovanni Cabiddu 	return __lzo_decompress(src, slen, dst, dlen);
1080b77abb3SZoltan Sogor }
1090b77abb3SZoltan Sogor 
1100b77abb3SZoltan Sogor static struct crypto_alg alg = {
1110b77abb3SZoltan Sogor 	.cra_name		= "lzo",
112*d6ebf528SEric Biggers 	.cra_driver_name	= "lzo-generic",
1130b77abb3SZoltan Sogor 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
1140b77abb3SZoltan Sogor 	.cra_ctxsize		= sizeof(struct lzo_ctx),
1150b77abb3SZoltan Sogor 	.cra_module		= THIS_MODULE,
1160b77abb3SZoltan Sogor 	.cra_init		= lzo_init,
1170b77abb3SZoltan Sogor 	.cra_exit		= lzo_exit,
1180b77abb3SZoltan Sogor 	.cra_u			= { .compress = {
1190b77abb3SZoltan Sogor 	.coa_compress		= lzo_compress,
1200b77abb3SZoltan Sogor 	.coa_decompress		= lzo_decompress } }
1210b77abb3SZoltan Sogor };
1220b77abb3SZoltan Sogor 
123ac9d2c4bSGiovanni Cabiddu static struct scomp_alg scomp = {
124ac9d2c4bSGiovanni Cabiddu 	.alloc_ctx		= lzo_alloc_ctx,
125ac9d2c4bSGiovanni Cabiddu 	.free_ctx		= lzo_free_ctx,
126ac9d2c4bSGiovanni Cabiddu 	.compress		= lzo_scompress,
127ac9d2c4bSGiovanni Cabiddu 	.decompress		= lzo_sdecompress,
128ac9d2c4bSGiovanni Cabiddu 	.base			= {
129ac9d2c4bSGiovanni Cabiddu 		.cra_name	= "lzo",
130ac9d2c4bSGiovanni Cabiddu 		.cra_driver_name = "lzo-scomp",
131ac9d2c4bSGiovanni Cabiddu 		.cra_module	 = THIS_MODULE,
132ac9d2c4bSGiovanni Cabiddu 	}
133ac9d2c4bSGiovanni Cabiddu };
134ac9d2c4bSGiovanni Cabiddu 
lzo_mod_init(void)1353af5b90bSKamalesh Babulal static int __init lzo_mod_init(void)
1360b77abb3SZoltan Sogor {
137ac9d2c4bSGiovanni Cabiddu 	int ret;
138ac9d2c4bSGiovanni Cabiddu 
139ac9d2c4bSGiovanni Cabiddu 	ret = crypto_register_alg(&alg);
140ac9d2c4bSGiovanni Cabiddu 	if (ret)
141ac9d2c4bSGiovanni Cabiddu 		return ret;
142ac9d2c4bSGiovanni Cabiddu 
143ac9d2c4bSGiovanni Cabiddu 	ret = crypto_register_scomp(&scomp);
144ac9d2c4bSGiovanni Cabiddu 	if (ret) {
145ac9d2c4bSGiovanni Cabiddu 		crypto_unregister_alg(&alg);
146ac9d2c4bSGiovanni Cabiddu 		return ret;
147ac9d2c4bSGiovanni Cabiddu 	}
148ac9d2c4bSGiovanni Cabiddu 
149ac9d2c4bSGiovanni Cabiddu 	return ret;
1500b77abb3SZoltan Sogor }
1510b77abb3SZoltan Sogor 
lzo_mod_fini(void)1523af5b90bSKamalesh Babulal static void __exit lzo_mod_fini(void)
1530b77abb3SZoltan Sogor {
1540b77abb3SZoltan Sogor 	crypto_unregister_alg(&alg);
155ac9d2c4bSGiovanni Cabiddu 	crypto_unregister_scomp(&scomp);
1560b77abb3SZoltan Sogor }
1570b77abb3SZoltan Sogor 
158c4741b23SEric Biggers subsys_initcall(lzo_mod_init);
1593af5b90bSKamalesh Babulal module_exit(lzo_mod_fini);
1600b77abb3SZoltan Sogor 
1610b77abb3SZoltan Sogor MODULE_LICENSE("GPL");
1620b77abb3SZoltan Sogor MODULE_DESCRIPTION("LZO Compression Algorithm");
1635d26a105SKees Cook MODULE_ALIAS_CRYPTO("lzo");
164