10ea8530dSChanho Min // 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>
130ea8530dSChanho Min #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)190ea8530dSChanho Min static void *lz4_alloc_ctx(struct crypto_scomp *tfm)
200ea8530dSChanho Min {
210ea8530dSChanho Min void *ctx;
220ea8530dSChanho Min
230ea8530dSChanho Min ctx = vmalloc(LZ4_MEM_COMPRESS);
240ea8530dSChanho Min if (!ctx)
250ea8530dSChanho Min return ERR_PTR(-ENOMEM);
268cd9330eSGiovanni Cabiddu
270ea8530dSChanho Min return ctx;
280ea8530dSChanho Min }
290ea8530dSChanho Min
lz4_init(struct crypto_tfm * tfm)300ea8530dSChanho Min static int lz4_init(struct crypto_tfm *tfm)
310ea8530dSChanho Min {
328cd9330eSGiovanni Cabiddu struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
338cd9330eSGiovanni Cabiddu
348cd9330eSGiovanni Cabiddu ctx->lz4_comp_mem = lz4_alloc_ctx(NULL);
358cd9330eSGiovanni Cabiddu if (IS_ERR(ctx->lz4_comp_mem))
368cd9330eSGiovanni Cabiddu return -ENOMEM;
378cd9330eSGiovanni Cabiddu
388cd9330eSGiovanni Cabiddu return 0;
398cd9330eSGiovanni Cabiddu }
408cd9330eSGiovanni Cabiddu
lz4_free_ctx(struct crypto_scomp * tfm,void * ctx)418cd9330eSGiovanni Cabiddu static void lz4_free_ctx(struct crypto_scomp *tfm, void *ctx)
428cd9330eSGiovanni Cabiddu {
430ea8530dSChanho Min vfree(ctx);
440ea8530dSChanho Min }
450ea8530dSChanho Min
lz4_exit(struct crypto_tfm * tfm)460ea8530dSChanho Min static void lz4_exit(struct crypto_tfm *tfm)
478cd9330eSGiovanni Cabiddu {
488cd9330eSGiovanni Cabiddu struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
490ea8530dSChanho Min
500ea8530dSChanho Min 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)530ea8530dSChanho Min static int __lz4_compress_crypto(const u8 *src, unsigned int slen,
548cd9330eSGiovanni Cabiddu u8 *dst, unsigned int *dlen, void *ctx)
558cd9330eSGiovanni Cabiddu {
568cd9330eSGiovanni Cabiddu int out_len = LZ4_compress_default(src, dst,
578cd9330eSGiovanni Cabiddu slen, *dlen, ctx);
588cd9330eSGiovanni Cabiddu
590ea8530dSChanho Min if (!out_len)
600ea8530dSChanho Min return -EINVAL;
610ea8530dSChanho Min
628cd9330eSGiovanni Cabiddu *dlen = out_len;
638cd9330eSGiovanni Cabiddu 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,
680ea8530dSChanho Min void *ctx)
6973a15ac6SSven Schmidt {
7073a15ac6SSven Schmidt return __lz4_compress_crypto(src, slen, dst, dlen, ctx);
710ea8530dSChanho Min }
7273a15ac6SSven Schmidt
lz4_compress_crypto(struct crypto_tfm * tfm,const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen)730ea8530dSChanho Min static int lz4_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
740ea8530dSChanho Min unsigned int slen, u8 *dst, unsigned int *dlen)
7573a15ac6SSven Schmidt {
760ea8530dSChanho Min struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
770ea8530dSChanho Min
780ea8530dSChanho Min 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 {
848cd9330eSGiovanni Cabiddu int out_len = LZ4_decompress_safe(src, dst, slen, *dlen);
858cd9330eSGiovanni Cabiddu
868cd9330eSGiovanni Cabiddu if (out_len < 0)
870ea8530dSChanho Min return -EINVAL;
880ea8530dSChanho Min
898cd9330eSGiovanni Cabiddu *dlen = out_len;
908cd9330eSGiovanni Cabiddu return 0;
918cd9330eSGiovanni Cabiddu }
928cd9330eSGiovanni Cabiddu
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 {
9773a15ac6SSven Schmidt return __lz4_decompress_crypto(src, slen, dst, dlen, NULL);
980ea8530dSChanho Min }
9973a15ac6SSven Schmidt
lz4_decompress_crypto(struct crypto_tfm * tfm,const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen)100cd15f102SMyungho Jung static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
1010ea8530dSChanho Min unsigned int slen, u8 *dst,
10273a15ac6SSven Schmidt unsigned int *dlen)
10373a15ac6SSven Schmidt {
1040ea8530dSChanho Min return __lz4_decompress_crypto(src, slen, dst, dlen, NULL);
1050ea8530dSChanho Min }
1068cd9330eSGiovanni Cabiddu
1078cd9330eSGiovanni Cabiddu static struct crypto_alg alg_lz4 = {
1088cd9330eSGiovanni Cabiddu .cra_name = "lz4",
1098cd9330eSGiovanni Cabiddu .cra_driver_name = "lz4-generic",
1108cd9330eSGiovanni Cabiddu .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
1118cd9330eSGiovanni Cabiddu .cra_ctxsize = sizeof(struct lz4_ctx),
1128cd9330eSGiovanni Cabiddu .cra_module = THIS_MODULE,
1138cd9330eSGiovanni Cabiddu .cra_init = lz4_init,
1148cd9330eSGiovanni Cabiddu .cra_exit = lz4_exit,
1158cd9330eSGiovanni Cabiddu .cra_u = { .compress = {
1168cd9330eSGiovanni Cabiddu .coa_compress = lz4_compress_crypto,
1178cd9330eSGiovanni Cabiddu .coa_decompress = lz4_decompress_crypto } }
1188cd9330eSGiovanni Cabiddu };
1198cd9330eSGiovanni Cabiddu
1200ea8530dSChanho Min static struct scomp_alg scomp = {
1210ea8530dSChanho Min .alloc_ctx = lz4_alloc_ctx,
122*d6ebf528SEric Biggers .free_ctx = lz4_free_ctx,
1230ea8530dSChanho Min .compress = lz4_scompress,
1240ea8530dSChanho Min .decompress = lz4_sdecompress,
1250ea8530dSChanho Min .base = {
1260ea8530dSChanho Min .cra_name = "lz4",
1270ea8530dSChanho Min .cra_driver_name = "lz4-scomp",
1280ea8530dSChanho Min .cra_module = THIS_MODULE,
1290ea8530dSChanho Min }
1300ea8530dSChanho Min };
1310ea8530dSChanho Min
lz4_mod_init(void)1320ea8530dSChanho Min static int __init lz4_mod_init(void)
1338cd9330eSGiovanni Cabiddu {
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 }
1450ea8530dSChanho Min
1460ea8530dSChanho Min return ret;
1478cd9330eSGiovanni Cabiddu }
1488cd9330eSGiovanni Cabiddu
lz4_mod_fini(void)1498cd9330eSGiovanni Cabiddu static void __exit lz4_mod_fini(void)
1508cd9330eSGiovanni Cabiddu {
1518cd9330eSGiovanni Cabiddu crypto_unregister_alg(&alg_lz4);
1528cd9330eSGiovanni Cabiddu crypto_unregister_scomp(&scomp);
1538cd9330eSGiovanni Cabiddu }
1548cd9330eSGiovanni Cabiddu
1558cd9330eSGiovanni Cabiddu subsys_initcall(lz4_mod_init);
1568cd9330eSGiovanni Cabiddu module_exit(lz4_mod_fini);
1578cd9330eSGiovanni Cabiddu
1588cd9330eSGiovanni Cabiddu MODULE_LICENSE("GPL");
1598cd9330eSGiovanni Cabiddu MODULE_DESCRIPTION("LZ4 Compression Algorithm");
1600ea8530dSChanho Min MODULE_ALIAS_CRYPTO("lz4");
1610ea8530dSChanho Min