1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Cryptographic API. |
4 | * |
5 | * Copyright (c) 2013 Chanho Min <chanho.min@lge.com> |
6 | */ |
7 | |
8 | #include <linux/init.h> |
9 | #include <linux/module.h> |
10 | #include <linux/crypto.h> |
11 | #include <linux/vmalloc.h> |
12 | #include <linux/lz4.h> |
13 | #include <crypto/internal/scompress.h> |
14 | |
15 | struct lz4_ctx { |
16 | void *lz4_comp_mem; |
17 | }; |
18 | |
19 | static void *lz4_alloc_ctx(struct crypto_scomp *tfm) |
20 | { |
21 | void *ctx; |
22 | |
23 | ctx = vmalloc(LZ4_MEM_COMPRESS); |
24 | if (!ctx) |
25 | return ERR_PTR(error: -ENOMEM); |
26 | |
27 | return ctx; |
28 | } |
29 | |
30 | static int lz4_init(struct crypto_tfm *tfm) |
31 | { |
32 | struct lz4_ctx *ctx = crypto_tfm_ctx(tfm); |
33 | |
34 | ctx->lz4_comp_mem = lz4_alloc_ctx(NULL); |
35 | if (IS_ERR(ptr: ctx->lz4_comp_mem)) |
36 | return -ENOMEM; |
37 | |
38 | return 0; |
39 | } |
40 | |
41 | static void lz4_free_ctx(struct crypto_scomp *tfm, void *ctx) |
42 | { |
43 | vfree(addr: ctx); |
44 | } |
45 | |
46 | static void lz4_exit(struct crypto_tfm *tfm) |
47 | { |
48 | struct lz4_ctx *ctx = crypto_tfm_ctx(tfm); |
49 | |
50 | lz4_free_ctx(NULL, ctx: ctx->lz4_comp_mem); |
51 | } |
52 | |
53 | static int __lz4_compress_crypto(const u8 *src, unsigned int slen, |
54 | u8 *dst, unsigned int *dlen, void *ctx) |
55 | { |
56 | int out_len = LZ4_compress_default(source: src, dest: dst, |
57 | inputSize: slen, maxOutputSize: *dlen, wrkmem: ctx); |
58 | |
59 | if (!out_len) |
60 | return -EINVAL; |
61 | |
62 | *dlen = out_len; |
63 | return 0; |
64 | } |
65 | |
66 | static int lz4_scompress(struct crypto_scomp *tfm, const u8 *src, |
67 | unsigned int slen, u8 *dst, unsigned int *dlen, |
68 | void *ctx) |
69 | { |
70 | return __lz4_compress_crypto(src, slen, dst, dlen, ctx); |
71 | } |
72 | |
73 | static int lz4_compress_crypto(struct crypto_tfm *tfm, const u8 *src, |
74 | unsigned int slen, u8 *dst, unsigned int *dlen) |
75 | { |
76 | struct lz4_ctx *ctx = crypto_tfm_ctx(tfm); |
77 | |
78 | return __lz4_compress_crypto(src, slen, dst, dlen, ctx: ctx->lz4_comp_mem); |
79 | } |
80 | |
81 | static int __lz4_decompress_crypto(const u8 *src, unsigned int slen, |
82 | u8 *dst, unsigned int *dlen, void *ctx) |
83 | { |
84 | int out_len = LZ4_decompress_safe(source: src, dest: dst, compressedSize: slen, maxDecompressedSize: *dlen); |
85 | |
86 | if (out_len < 0) |
87 | return -EINVAL; |
88 | |
89 | *dlen = out_len; |
90 | return 0; |
91 | } |
92 | |
93 | static int lz4_sdecompress(struct crypto_scomp *tfm, const u8 *src, |
94 | unsigned int slen, u8 *dst, unsigned int *dlen, |
95 | void *ctx) |
96 | { |
97 | return __lz4_decompress_crypto(src, slen, dst, dlen, NULL); |
98 | } |
99 | |
100 | static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src, |
101 | unsigned int slen, u8 *dst, |
102 | unsigned int *dlen) |
103 | { |
104 | return __lz4_decompress_crypto(src, slen, dst, dlen, NULL); |
105 | } |
106 | |
107 | static struct crypto_alg alg_lz4 = { |
108 | .cra_name = "lz4" , |
109 | .cra_driver_name = "lz4-generic" , |
110 | .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, |
111 | .cra_ctxsize = sizeof(struct lz4_ctx), |
112 | .cra_module = THIS_MODULE, |
113 | .cra_init = lz4_init, |
114 | .cra_exit = lz4_exit, |
115 | .cra_u = { .compress = { |
116 | .coa_compress = lz4_compress_crypto, |
117 | .coa_decompress = lz4_decompress_crypto } } |
118 | }; |
119 | |
120 | static struct scomp_alg scomp = { |
121 | .alloc_ctx = lz4_alloc_ctx, |
122 | .free_ctx = lz4_free_ctx, |
123 | .compress = lz4_scompress, |
124 | .decompress = lz4_sdecompress, |
125 | .base = { |
126 | .cra_name = "lz4" , |
127 | .cra_driver_name = "lz4-scomp" , |
128 | .cra_module = THIS_MODULE, |
129 | } |
130 | }; |
131 | |
132 | static int __init lz4_mod_init(void) |
133 | { |
134 | int ret; |
135 | |
136 | ret = crypto_register_alg(alg: &alg_lz4); |
137 | if (ret) |
138 | return ret; |
139 | |
140 | ret = crypto_register_scomp(alg: &scomp); |
141 | if (ret) { |
142 | crypto_unregister_alg(alg: &alg_lz4); |
143 | return ret; |
144 | } |
145 | |
146 | return ret; |
147 | } |
148 | |
149 | static void __exit lz4_mod_fini(void) |
150 | { |
151 | crypto_unregister_alg(alg: &alg_lz4); |
152 | crypto_unregister_scomp(alg: &scomp); |
153 | } |
154 | |
155 | subsys_initcall(lz4_mod_init); |
156 | module_exit(lz4_mod_fini); |
157 | |
158 | MODULE_LICENSE("GPL" ); |
159 | MODULE_DESCRIPTION("LZ4 Compression Algorithm" ); |
160 | MODULE_ALIAS_CRYPTO("lz4" ); |
161 | |