]>
Commit | Line | Data |
---|---|---|
0b77abb3 ZS |
1 | /* |
2 | * Cryptographic API. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms of the GNU General Public License version 2 as published by | |
6 | * the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
11 | * more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License along with | |
14 | * this program; if not, write to the Free Software Foundation, Inc., 51 | |
15 | * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
16 | * | |
17 | */ | |
18 | ||
19 | #include <linux/init.h> | |
20 | #include <linux/module.h> | |
21 | #include <linux/crypto.h> | |
22 | #include <linux/vmalloc.h> | |
42614b05 | 23 | #include <linux/mm.h> |
0b77abb3 | 24 | #include <linux/lzo.h> |
ac9d2c4b | 25 | #include <crypto/internal/scompress.h> |
0b77abb3 ZS |
26 | |
27 | struct lzo_ctx { | |
28 | void *lzo_comp_mem; | |
29 | }; | |
30 | ||
ac9d2c4b GC |
31 | static void *lzo_alloc_ctx(struct crypto_scomp *tfm) |
32 | { | |
33 | void *ctx; | |
34 | ||
35 | ctx = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL | __GFP_NOWARN); | |
36 | if (!ctx) | |
37 | ctx = vmalloc(LZO1X_MEM_COMPRESS); | |
38 | if (!ctx) | |
39 | return ERR_PTR(-ENOMEM); | |
40 | ||
41 | return ctx; | |
42 | } | |
43 | ||
0b77abb3 ZS |
44 | static int lzo_init(struct crypto_tfm *tfm) |
45 | { | |
46 | struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); | |
47 | ||
ac9d2c4b GC |
48 | ctx->lzo_comp_mem = lzo_alloc_ctx(NULL); |
49 | if (IS_ERR(ctx->lzo_comp_mem)) | |
0b77abb3 ZS |
50 | return -ENOMEM; |
51 | ||
52 | return 0; | |
53 | } | |
54 | ||
ac9d2c4b GC |
55 | static void lzo_free_ctx(struct crypto_scomp *tfm, void *ctx) |
56 | { | |
57 | kvfree(ctx); | |
58 | } | |
59 | ||
0b77abb3 ZS |
60 | static void lzo_exit(struct crypto_tfm *tfm) |
61 | { | |
62 | struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); | |
63 | ||
ac9d2c4b | 64 | lzo_free_ctx(NULL, ctx->lzo_comp_mem); |
0b77abb3 ZS |
65 | } |
66 | ||
ac9d2c4b GC |
67 | static int __lzo_compress(const u8 *src, unsigned int slen, |
68 | u8 *dst, unsigned int *dlen, void *ctx) | |
0b77abb3 | 69 | { |
0b77abb3 ZS |
70 | size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */ |
71 | int err; | |
72 | ||
ac9d2c4b | 73 | err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx); |
0b77abb3 ZS |
74 | |
75 | if (err != LZO_E_OK) | |
76 | return -EINVAL; | |
77 | ||
78 | *dlen = tmp_len; | |
79 | return 0; | |
80 | } | |
81 | ||
ac9d2c4b GC |
82 | static int lzo_compress(struct crypto_tfm *tfm, const u8 *src, |
83 | unsigned int slen, u8 *dst, unsigned int *dlen) | |
84 | { | |
85 | struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); | |
86 | ||
87 | return __lzo_compress(src, slen, dst, dlen, ctx->lzo_comp_mem); | |
88 | } | |
89 | ||
90 | static int lzo_scompress(struct crypto_scomp *tfm, const u8 *src, | |
91 | unsigned int slen, u8 *dst, unsigned int *dlen, | |
92 | void *ctx) | |
93 | { | |
94 | return __lzo_compress(src, slen, dst, dlen, ctx); | |
95 | } | |
96 | ||
97 | static int __lzo_decompress(const u8 *src, unsigned int slen, | |
98 | u8 *dst, unsigned int *dlen) | |
0b77abb3 ZS |
99 | { |
100 | int err; | |
101 | size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */ | |
102 | ||
103 | err = lzo1x_decompress_safe(src, slen, dst, &tmp_len); | |
104 | ||
105 | if (err != LZO_E_OK) | |
106 | return -EINVAL; | |
107 | ||
108 | *dlen = tmp_len; | |
109 | return 0; | |
ac9d2c4b | 110 | } |
0b77abb3 | 111 | |
ac9d2c4b GC |
112 | static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src, |
113 | unsigned int slen, u8 *dst, unsigned int *dlen) | |
114 | { | |
115 | return __lzo_decompress(src, slen, dst, dlen); | |
116 | } | |
117 | ||
118 | static int lzo_sdecompress(struct crypto_scomp *tfm, const u8 *src, | |
119 | unsigned int slen, u8 *dst, unsigned int *dlen, | |
120 | void *ctx) | |
121 | { | |
122 | return __lzo_decompress(src, slen, dst, dlen); | |
0b77abb3 ZS |
123 | } |
124 | ||
125 | static struct crypto_alg alg = { | |
126 | .cra_name = "lzo", | |
127 | .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, | |
128 | .cra_ctxsize = sizeof(struct lzo_ctx), | |
129 | .cra_module = THIS_MODULE, | |
0b77abb3 ZS |
130 | .cra_init = lzo_init, |
131 | .cra_exit = lzo_exit, | |
132 | .cra_u = { .compress = { | |
ac9d2c4b GC |
133 | .coa_compress = lzo_compress, |
134 | .coa_decompress = lzo_decompress } } | |
135 | }; | |
136 | ||
137 | static struct scomp_alg scomp = { | |
138 | .alloc_ctx = lzo_alloc_ctx, | |
139 | .free_ctx = lzo_free_ctx, | |
140 | .compress = lzo_scompress, | |
141 | .decompress = lzo_sdecompress, | |
142 | .base = { | |
143 | .cra_name = "lzo", | |
144 | .cra_driver_name = "lzo-scomp", | |
145 | .cra_module = THIS_MODULE, | |
146 | } | |
0b77abb3 ZS |
147 | }; |
148 | ||
3af5b90b | 149 | static int __init lzo_mod_init(void) |
0b77abb3 | 150 | { |
ac9d2c4b GC |
151 | int ret; |
152 | ||
153 | ret = crypto_register_alg(&alg); | |
154 | if (ret) | |
155 | return ret; | |
156 | ||
157 | ret = crypto_register_scomp(&scomp); | |
158 | if (ret) { | |
159 | crypto_unregister_alg(&alg); | |
160 | return ret; | |
161 | } | |
162 | ||
163 | return ret; | |
0b77abb3 ZS |
164 | } |
165 | ||
3af5b90b | 166 | static void __exit lzo_mod_fini(void) |
0b77abb3 ZS |
167 | { |
168 | crypto_unregister_alg(&alg); | |
ac9d2c4b | 169 | crypto_unregister_scomp(&scomp); |
0b77abb3 ZS |
170 | } |
171 | ||
3af5b90b KB |
172 | module_init(lzo_mod_init); |
173 | module_exit(lzo_mod_fini); | |
0b77abb3 ZS |
174 | |
175 | MODULE_LICENSE("GPL"); | |
176 | MODULE_DESCRIPTION("LZO Compression Algorithm"); | |
5d26a105 | 177 | MODULE_ALIAS_CRYPTO("lzo"); |