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