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 { 6873a15ac6SSven Schmidt int out_len = LZ4_compress_HC(src, dst, slen, 6973a15ac6SSven Schmidt *dlen, LZ4HC_DEFAULT_CLEVEL, ctx); 700ea8530dSChanho Min 7173a15ac6SSven Schmidt if (!out_len) 720ea8530dSChanho Min return -EINVAL; 730ea8530dSChanho Min 7473a15ac6SSven 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 { 9873a15ac6SSven Schmidt int out_len = LZ4_decompress_safe(src, dst, slen, *dlen); 990ea8530dSChanho Min 10073a15ac6SSven Schmidt if (out_len < 0) 101cd15f102SMyungho Jung return -EINVAL; 1020ea8530dSChanho Min 10373a15ac6SSven Schmidt *dlen = out_len; 10473a15ac6SSven 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_init = lz4hc_init, 1270ea8530dSChanho Min .cra_exit = lz4hc_exit, 1280ea8530dSChanho Min .cra_u = { .compress = { 1290ea8530dSChanho Min .coa_compress = lz4hc_compress_crypto, 1300ea8530dSChanho Min .coa_decompress = lz4hc_decompress_crypto } } 1310ea8530dSChanho Min }; 1320ea8530dSChanho Min 13391d53d96SGiovanni Cabiddu static struct scomp_alg scomp = { 13491d53d96SGiovanni Cabiddu .alloc_ctx = lz4hc_alloc_ctx, 13591d53d96SGiovanni Cabiddu .free_ctx = lz4hc_free_ctx, 13691d53d96SGiovanni Cabiddu .compress = lz4hc_scompress, 13791d53d96SGiovanni Cabiddu .decompress = lz4hc_sdecompress, 13891d53d96SGiovanni Cabiddu .base = { 13991d53d96SGiovanni Cabiddu .cra_name = "lz4hc", 14091d53d96SGiovanni Cabiddu .cra_driver_name = "lz4hc-scomp", 14191d53d96SGiovanni Cabiddu .cra_module = THIS_MODULE, 14291d53d96SGiovanni Cabiddu } 14391d53d96SGiovanni Cabiddu }; 14491d53d96SGiovanni Cabiddu 1450ea8530dSChanho Min static int __init lz4hc_mod_init(void) 1460ea8530dSChanho Min { 14791d53d96SGiovanni Cabiddu int ret; 14891d53d96SGiovanni Cabiddu 14991d53d96SGiovanni Cabiddu ret = crypto_register_alg(&alg_lz4hc); 15091d53d96SGiovanni Cabiddu if (ret) 15191d53d96SGiovanni Cabiddu return ret; 15291d53d96SGiovanni Cabiddu 15391d53d96SGiovanni Cabiddu ret = crypto_register_scomp(&scomp); 15491d53d96SGiovanni Cabiddu if (ret) { 15591d53d96SGiovanni Cabiddu crypto_unregister_alg(&alg_lz4hc); 15691d53d96SGiovanni Cabiddu return ret; 15791d53d96SGiovanni Cabiddu } 15891d53d96SGiovanni Cabiddu 15991d53d96SGiovanni Cabiddu return ret; 1600ea8530dSChanho Min } 1610ea8530dSChanho Min 1620ea8530dSChanho Min static void __exit lz4hc_mod_fini(void) 1630ea8530dSChanho Min { 1640ea8530dSChanho Min crypto_unregister_alg(&alg_lz4hc); 16591d53d96SGiovanni Cabiddu crypto_unregister_scomp(&scomp); 1660ea8530dSChanho Min } 1670ea8530dSChanho Min 168*c4741b23SEric Biggers subsys_initcall(lz4hc_mod_init); 1690ea8530dSChanho Min module_exit(lz4hc_mod_fini); 1700ea8530dSChanho Min 1710ea8530dSChanho Min MODULE_LICENSE("GPL"); 1720ea8530dSChanho Min MODULE_DESCRIPTION("LZ4HC Compression Algorithm"); 1735d26a105SKees Cook MODULE_ALIAS_CRYPTO("lz4hc"); 174