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> 25*91d53d96SGiovanni Cabiddu #include <crypto/internal/scompress.h> 260ea8530dSChanho Min 270ea8530dSChanho Min struct lz4hc_ctx { 280ea8530dSChanho Min void *lz4hc_comp_mem; 290ea8530dSChanho Min }; 300ea8530dSChanho Min 31*91d53d96SGiovanni Cabiddu static void *lz4hc_alloc_ctx(struct crypto_scomp *tfm) 32*91d53d96SGiovanni Cabiddu { 33*91d53d96SGiovanni Cabiddu void *ctx; 34*91d53d96SGiovanni Cabiddu 35*91d53d96SGiovanni Cabiddu ctx = vmalloc(LZ4HC_MEM_COMPRESS); 36*91d53d96SGiovanni Cabiddu if (!ctx) 37*91d53d96SGiovanni Cabiddu return ERR_PTR(-ENOMEM); 38*91d53d96SGiovanni Cabiddu 39*91d53d96SGiovanni Cabiddu return ctx; 40*91d53d96SGiovanni Cabiddu } 41*91d53d96SGiovanni 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 46*91d53d96SGiovanni Cabiddu ctx->lz4hc_comp_mem = lz4hc_alloc_ctx(NULL); 47*91d53d96SGiovanni Cabiddu if (IS_ERR(ctx->lz4hc_comp_mem)) 480ea8530dSChanho Min return -ENOMEM; 490ea8530dSChanho Min 500ea8530dSChanho Min return 0; 510ea8530dSChanho Min } 520ea8530dSChanho Min 53*91d53d96SGiovanni Cabiddu static void lz4hc_free_ctx(struct crypto_scomp *tfm, void *ctx) 54*91d53d96SGiovanni Cabiddu { 55*91d53d96SGiovanni Cabiddu vfree(ctx); 56*91d53d96SGiovanni Cabiddu } 57*91d53d96SGiovanni 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 62*91d53d96SGiovanni Cabiddu lz4hc_free_ctx(NULL, ctx->lz4hc_comp_mem); 630ea8530dSChanho Min } 640ea8530dSChanho Min 65*91d53d96SGiovanni Cabiddu static int __lz4hc_compress_crypto(const u8 *src, unsigned int slen, 66*91d53d96SGiovanni Cabiddu u8 *dst, unsigned int *dlen, void *ctx) 670ea8530dSChanho Min { 680ea8530dSChanho Min size_t tmp_len = *dlen; 690ea8530dSChanho Min int err; 700ea8530dSChanho Min 71*91d53d96SGiovanni Cabiddu err = lz4hc_compress(src, slen, dst, &tmp_len, ctx); 720ea8530dSChanho Min 730ea8530dSChanho Min if (err < 0) 740ea8530dSChanho Min return -EINVAL; 750ea8530dSChanho Min 760ea8530dSChanho Min *dlen = tmp_len; 770ea8530dSChanho Min return 0; 780ea8530dSChanho Min } 790ea8530dSChanho Min 80*91d53d96SGiovanni Cabiddu static int lz4hc_scompress(struct crypto_scomp *tfm, const u8 *src, 81*91d53d96SGiovanni Cabiddu unsigned int slen, u8 *dst, unsigned int *dlen, 82*91d53d96SGiovanni Cabiddu void *ctx) 83*91d53d96SGiovanni Cabiddu { 84*91d53d96SGiovanni Cabiddu return __lz4hc_compress_crypto(src, slen, dst, dlen, ctx); 85*91d53d96SGiovanni Cabiddu } 86*91d53d96SGiovanni Cabiddu 87*91d53d96SGiovanni Cabiddu static int lz4hc_compress_crypto(struct crypto_tfm *tfm, const u8 *src, 88*91d53d96SGiovanni Cabiddu unsigned int slen, u8 *dst, 89*91d53d96SGiovanni Cabiddu unsigned int *dlen) 90*91d53d96SGiovanni Cabiddu { 91*91d53d96SGiovanni Cabiddu struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm); 92*91d53d96SGiovanni Cabiddu 93*91d53d96SGiovanni Cabiddu return __lz4hc_compress_crypto(src, slen, dst, dlen, 94*91d53d96SGiovanni Cabiddu ctx->lz4hc_comp_mem); 95*91d53d96SGiovanni Cabiddu } 96*91d53d96SGiovanni Cabiddu 97*91d53d96SGiovanni Cabiddu static int __lz4hc_decompress_crypto(const u8 *src, unsigned int slen, 98*91d53d96SGiovanni Cabiddu u8 *dst, unsigned int *dlen, void *ctx) 990ea8530dSChanho Min { 1000ea8530dSChanho Min int err; 1010ea8530dSChanho Min size_t tmp_len = *dlen; 1020ea8530dSChanho Min size_t __slen = slen; 1030ea8530dSChanho Min 104d801ab20SKOVACS Krisztian err = lz4_decompress_unknownoutputsize(src, __slen, dst, &tmp_len); 1050ea8530dSChanho Min if (err < 0) 1060ea8530dSChanho Min return -EINVAL; 1070ea8530dSChanho Min 1080ea8530dSChanho Min *dlen = tmp_len; 1090ea8530dSChanho Min return err; 1100ea8530dSChanho Min } 1110ea8530dSChanho Min 112*91d53d96SGiovanni Cabiddu static int lz4hc_sdecompress(struct crypto_scomp *tfm, const u8 *src, 113*91d53d96SGiovanni Cabiddu unsigned int slen, u8 *dst, unsigned int *dlen, 114*91d53d96SGiovanni Cabiddu void *ctx) 115*91d53d96SGiovanni Cabiddu { 116*91d53d96SGiovanni Cabiddu return __lz4hc_decompress_crypto(src, slen, dst, dlen, NULL); 117*91d53d96SGiovanni Cabiddu } 118*91d53d96SGiovanni Cabiddu 119*91d53d96SGiovanni Cabiddu static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src, 120*91d53d96SGiovanni Cabiddu unsigned int slen, u8 *dst, 121*91d53d96SGiovanni Cabiddu unsigned int *dlen) 122*91d53d96SGiovanni Cabiddu { 123*91d53d96SGiovanni Cabiddu return __lz4hc_decompress_crypto(src, slen, dst, dlen, NULL); 124*91d53d96SGiovanni Cabiddu } 125*91d53d96SGiovanni Cabiddu 1260ea8530dSChanho Min static struct crypto_alg alg_lz4hc = { 1270ea8530dSChanho Min .cra_name = "lz4hc", 1280ea8530dSChanho Min .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, 1290ea8530dSChanho Min .cra_ctxsize = sizeof(struct lz4hc_ctx), 1300ea8530dSChanho Min .cra_module = THIS_MODULE, 1310ea8530dSChanho Min .cra_list = LIST_HEAD_INIT(alg_lz4hc.cra_list), 1320ea8530dSChanho Min .cra_init = lz4hc_init, 1330ea8530dSChanho Min .cra_exit = lz4hc_exit, 1340ea8530dSChanho Min .cra_u = { .compress = { 1350ea8530dSChanho Min .coa_compress = lz4hc_compress_crypto, 1360ea8530dSChanho Min .coa_decompress = lz4hc_decompress_crypto } } 1370ea8530dSChanho Min }; 1380ea8530dSChanho Min 139*91d53d96SGiovanni Cabiddu static struct scomp_alg scomp = { 140*91d53d96SGiovanni Cabiddu .alloc_ctx = lz4hc_alloc_ctx, 141*91d53d96SGiovanni Cabiddu .free_ctx = lz4hc_free_ctx, 142*91d53d96SGiovanni Cabiddu .compress = lz4hc_scompress, 143*91d53d96SGiovanni Cabiddu .decompress = lz4hc_sdecompress, 144*91d53d96SGiovanni Cabiddu .base = { 145*91d53d96SGiovanni Cabiddu .cra_name = "lz4hc", 146*91d53d96SGiovanni Cabiddu .cra_driver_name = "lz4hc-scomp", 147*91d53d96SGiovanni Cabiddu .cra_module = THIS_MODULE, 148*91d53d96SGiovanni Cabiddu } 149*91d53d96SGiovanni Cabiddu }; 150*91d53d96SGiovanni Cabiddu 1510ea8530dSChanho Min static int __init lz4hc_mod_init(void) 1520ea8530dSChanho Min { 153*91d53d96SGiovanni Cabiddu int ret; 154*91d53d96SGiovanni Cabiddu 155*91d53d96SGiovanni Cabiddu ret = crypto_register_alg(&alg_lz4hc); 156*91d53d96SGiovanni Cabiddu if (ret) 157*91d53d96SGiovanni Cabiddu return ret; 158*91d53d96SGiovanni Cabiddu 159*91d53d96SGiovanni Cabiddu ret = crypto_register_scomp(&scomp); 160*91d53d96SGiovanni Cabiddu if (ret) { 161*91d53d96SGiovanni Cabiddu crypto_unregister_alg(&alg_lz4hc); 162*91d53d96SGiovanni Cabiddu return ret; 163*91d53d96SGiovanni Cabiddu } 164*91d53d96SGiovanni Cabiddu 165*91d53d96SGiovanni Cabiddu return ret; 1660ea8530dSChanho Min } 1670ea8530dSChanho Min 1680ea8530dSChanho Min static void __exit lz4hc_mod_fini(void) 1690ea8530dSChanho Min { 1700ea8530dSChanho Min crypto_unregister_alg(&alg_lz4hc); 171*91d53d96SGiovanni Cabiddu crypto_unregister_scomp(&scomp); 1720ea8530dSChanho Min } 1730ea8530dSChanho Min 1740ea8530dSChanho Min module_init(lz4hc_mod_init); 1750ea8530dSChanho Min module_exit(lz4hc_mod_fini); 1760ea8530dSChanho Min 1770ea8530dSChanho Min MODULE_LICENSE("GPL"); 1780ea8530dSChanho Min MODULE_DESCRIPTION("LZ4HC Compression Algorithm"); 1795d26a105SKees Cook MODULE_ALIAS_CRYPTO("lz4hc"); 180