Merge branch 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6
[pandora-kernel.git] / crypto / zlib.c
1 /*
2  * Cryptographic API.
3  *
4  * Zlib algorithm
5  *
6  * Copyright 2008 Sony Corporation
7  *
8  * Based on deflate.c, which is
9  * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License as published by the Free
13  * Software Foundation; either version 2 of the License, or (at your option)
14  * any later version.
15  *
16  * FIXME: deflate transforms will require up to a total of about 436k of kernel
17  * memory on i386 (390k for compression, the rest for decompression), as the
18  * current zlib kernel code uses a worst case pre-allocation system by default.
19  * This needs to be fixed so that the amount of memory required is properly
20  * related to the winbits and memlevel parameters.
21  */
22
23 #define pr_fmt(fmt)     "%s: " fmt, __func__
24
25 #include <linux/init.h>
26 #include <linux/module.h>
27 #include <linux/zlib.h>
28 #include <linux/vmalloc.h>
29 #include <linux/interrupt.h>
30 #include <linux/mm.h>
31 #include <linux/net.h>
32 #include <linux/slab.h>
33
34 #include <crypto/internal/compress.h>
35
36 #include <net/netlink.h>
37
38
39 struct zlib_ctx {
40         struct z_stream_s comp_stream;
41         struct z_stream_s decomp_stream;
42         int decomp_windowBits;
43 };
44
45
46 static void zlib_comp_exit(struct zlib_ctx *ctx)
47 {
48         struct z_stream_s *stream = &ctx->comp_stream;
49
50         if (stream->workspace) {
51                 zlib_deflateEnd(stream);
52                 vfree(stream->workspace);
53                 stream->workspace = NULL;
54         }
55 }
56
57 static void zlib_decomp_exit(struct zlib_ctx *ctx)
58 {
59         struct z_stream_s *stream = &ctx->decomp_stream;
60
61         if (stream->workspace) {
62                 zlib_inflateEnd(stream);
63                 kfree(stream->workspace);
64                 stream->workspace = NULL;
65         }
66 }
67
68 static int zlib_init(struct crypto_tfm *tfm)
69 {
70         return 0;
71 }
72
73 static void zlib_exit(struct crypto_tfm *tfm)
74 {
75         struct zlib_ctx *ctx = crypto_tfm_ctx(tfm);
76
77         zlib_comp_exit(ctx);
78         zlib_decomp_exit(ctx);
79 }
80
81
82 static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params,
83                                unsigned int len)
84 {
85         struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
86         struct z_stream_s *stream = &ctx->comp_stream;
87         struct nlattr *tb[ZLIB_COMP_MAX + 1];
88         int window_bits, mem_level;
89         size_t workspacesize;
90         int ret;
91
92         ret = nla_parse(tb, ZLIB_COMP_MAX, params, len, NULL);
93         if (ret)
94                 return ret;
95
96         zlib_comp_exit(ctx);
97
98         window_bits = tb[ZLIB_COMP_WINDOWBITS]
99                                         ? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS])
100                                         : MAX_WBITS;
101         mem_level = tb[ZLIB_COMP_MEMLEVEL]
102                                         ? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL])
103                                         : DEF_MEM_LEVEL;
104
105         workspacesize = zlib_deflate_workspacesize(window_bits, mem_level);
106         stream->workspace = vzalloc(workspacesize);
107         if (!stream->workspace)
108                 return -ENOMEM;
109
110         ret = zlib_deflateInit2(stream,
111                                 tb[ZLIB_COMP_LEVEL]
112                                         ? nla_get_u32(tb[ZLIB_COMP_LEVEL])
113                                         : Z_DEFAULT_COMPRESSION,
114                                 tb[ZLIB_COMP_METHOD]
115                                         ? nla_get_u32(tb[ZLIB_COMP_METHOD])
116                                         : Z_DEFLATED,
117                                 window_bits,
118                                 mem_level,
119                                 tb[ZLIB_COMP_STRATEGY]
120                                         ? nla_get_u32(tb[ZLIB_COMP_STRATEGY])
121                                         : Z_DEFAULT_STRATEGY);
122         if (ret != Z_OK) {
123                 vfree(stream->workspace);
124                 stream->workspace = NULL;
125                 return -EINVAL;
126         }
127
128         return 0;
129 }
130
131 static int zlib_compress_init(struct crypto_pcomp *tfm)
132 {
133         int ret;
134         struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
135         struct z_stream_s *stream = &dctx->comp_stream;
136
137         ret = zlib_deflateReset(stream);
138         if (ret != Z_OK)
139                 return -EINVAL;
140
141         return 0;
142 }
143
144 static int zlib_compress_update(struct crypto_pcomp *tfm,
145                                 struct comp_request *req)
146 {
147         int ret;
148         struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
149         struct z_stream_s *stream = &dctx->comp_stream;
150
151         pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
152         stream->next_in = req->next_in;
153         stream->avail_in = req->avail_in;
154         stream->next_out = req->next_out;
155         stream->avail_out = req->avail_out;
156
157         ret = zlib_deflate(stream, Z_NO_FLUSH);
158         switch (ret) {
159         case Z_OK:
160                 break;
161
162         case Z_BUF_ERROR:
163                 pr_debug("zlib_deflate could not make progress\n");
164                 return -EAGAIN;
165
166         default:
167                 pr_debug("zlib_deflate failed %d\n", ret);
168                 return -EINVAL;
169         }
170
171         ret = req->avail_out - stream->avail_out;
172         pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
173                  stream->avail_in, stream->avail_out,
174                  req->avail_in - stream->avail_in, ret);
175         req->next_in = stream->next_in;
176         req->avail_in = stream->avail_in;
177         req->next_out = stream->next_out;
178         req->avail_out = stream->avail_out;
179         return ret;
180 }
181
182 static int zlib_compress_final(struct crypto_pcomp *tfm,
183                                struct comp_request *req)
184 {
185         int ret;
186         struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
187         struct z_stream_s *stream = &dctx->comp_stream;
188
189         pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
190         stream->next_in = req->next_in;
191         stream->avail_in = req->avail_in;
192         stream->next_out = req->next_out;
193         stream->avail_out = req->avail_out;
194
195         ret = zlib_deflate(stream, Z_FINISH);
196         if (ret != Z_STREAM_END) {
197                 pr_debug("zlib_deflate failed %d\n", ret);
198                 return -EINVAL;
199         }
200
201         ret = req->avail_out - stream->avail_out;
202         pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
203                  stream->avail_in, stream->avail_out,
204                  req->avail_in - stream->avail_in, ret);
205         req->next_in = stream->next_in;
206         req->avail_in = stream->avail_in;
207         req->next_out = stream->next_out;
208         req->avail_out = stream->avail_out;
209         return ret;
210 }
211
212
213 static int zlib_decompress_setup(struct crypto_pcomp *tfm, void *params,
214                                  unsigned int len)
215 {
216         struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
217         struct z_stream_s *stream = &ctx->decomp_stream;
218         struct nlattr *tb[ZLIB_DECOMP_MAX + 1];
219         int ret = 0;
220
221         ret = nla_parse(tb, ZLIB_DECOMP_MAX, params, len, NULL);
222         if (ret)
223                 return ret;
224
225         zlib_decomp_exit(ctx);
226
227         ctx->decomp_windowBits = tb[ZLIB_DECOMP_WINDOWBITS]
228                                  ? nla_get_u32(tb[ZLIB_DECOMP_WINDOWBITS])
229                                  : DEF_WBITS;
230
231         stream->workspace = kzalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
232         if (!stream->workspace)
233                 return -ENOMEM;
234
235         ret = zlib_inflateInit2(stream, ctx->decomp_windowBits);
236         if (ret != Z_OK) {
237                 kfree(stream->workspace);
238                 stream->workspace = NULL;
239                 return -EINVAL;
240         }
241
242         return 0;
243 }
244
245 static int zlib_decompress_init(struct crypto_pcomp *tfm)
246 {
247         int ret;
248         struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
249         struct z_stream_s *stream = &dctx->decomp_stream;
250
251         ret = zlib_inflateReset(stream);
252         if (ret != Z_OK)
253                 return -EINVAL;
254
255         return 0;
256 }
257
258 static int zlib_decompress_update(struct crypto_pcomp *tfm,
259                                   struct comp_request *req)
260 {
261         int ret;
262         struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
263         struct z_stream_s *stream = &dctx->decomp_stream;
264
265         pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
266         stream->next_in = req->next_in;
267         stream->avail_in = req->avail_in;
268         stream->next_out = req->next_out;
269         stream->avail_out = req->avail_out;
270
271         ret = zlib_inflate(stream, Z_SYNC_FLUSH);
272         switch (ret) {
273         case Z_OK:
274         case Z_STREAM_END:
275                 break;
276
277         case Z_BUF_ERROR:
278                 pr_debug("zlib_inflate could not make progress\n");
279                 return -EAGAIN;
280
281         default:
282                 pr_debug("zlib_inflate failed %d\n", ret);
283                 return -EINVAL;
284         }
285
286         ret = req->avail_out - stream->avail_out;
287         pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
288                  stream->avail_in, stream->avail_out,
289                  req->avail_in - stream->avail_in, ret);
290         req->next_in = stream->next_in;
291         req->avail_in = stream->avail_in;
292         req->next_out = stream->next_out;
293         req->avail_out = stream->avail_out;
294         return ret;
295 }
296
297 static int zlib_decompress_final(struct crypto_pcomp *tfm,
298                                  struct comp_request *req)
299 {
300         int ret;
301         struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
302         struct z_stream_s *stream = &dctx->decomp_stream;
303
304         pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
305         stream->next_in = req->next_in;
306         stream->avail_in = req->avail_in;
307         stream->next_out = req->next_out;
308         stream->avail_out = req->avail_out;
309
310         if (dctx->decomp_windowBits < 0) {
311                 ret = zlib_inflate(stream, Z_SYNC_FLUSH);
312                 /*
313                  * Work around a bug in zlib, which sometimes wants to taste an
314                  * extra byte when being used in the (undocumented) raw deflate
315                  * mode. (From USAGI).
316                  */
317                 if (ret == Z_OK && !stream->avail_in && stream->avail_out) {
318                         const void *saved_next_in = stream->next_in;
319                         u8 zerostuff = 0;
320
321                         stream->next_in = &zerostuff;
322                         stream->avail_in = 1;
323                         ret = zlib_inflate(stream, Z_FINISH);
324                         stream->next_in = saved_next_in;
325                         stream->avail_in = 0;
326                 }
327         } else
328                 ret = zlib_inflate(stream, Z_FINISH);
329         if (ret != Z_STREAM_END) {
330                 pr_debug("zlib_inflate failed %d\n", ret);
331                 return -EINVAL;
332         }
333
334         ret = req->avail_out - stream->avail_out;
335         pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
336                  stream->avail_in, stream->avail_out,
337                  req->avail_in - stream->avail_in, ret);
338         req->next_in = stream->next_in;
339         req->avail_in = stream->avail_in;
340         req->next_out = stream->next_out;
341         req->avail_out = stream->avail_out;
342         return ret;
343 }
344
345
346 static struct pcomp_alg zlib_alg = {
347         .compress_setup         = zlib_compress_setup,
348         .compress_init          = zlib_compress_init,
349         .compress_update        = zlib_compress_update,
350         .compress_final         = zlib_compress_final,
351         .decompress_setup       = zlib_decompress_setup,
352         .decompress_init        = zlib_decompress_init,
353         .decompress_update      = zlib_decompress_update,
354         .decompress_final       = zlib_decompress_final,
355
356         .base                   = {
357                 .cra_name       = "zlib",
358                 .cra_flags      = CRYPTO_ALG_TYPE_PCOMPRESS,
359                 .cra_ctxsize    = sizeof(struct zlib_ctx),
360                 .cra_module     = THIS_MODULE,
361                 .cra_init       = zlib_init,
362                 .cra_exit       = zlib_exit,
363         }
364 };
365
366 static int __init zlib_mod_init(void)
367 {
368         return crypto_register_pcomp(&zlib_alg);
369 }
370
371 static void __exit zlib_mod_fini(void)
372 {
373         crypto_unregister_pcomp(&zlib_alg);
374 }
375
376 module_init(zlib_mod_init);
377 module_exit(zlib_mod_fini);
378
379 MODULE_LICENSE("GPL");
380 MODULE_DESCRIPTION("Zlib Compression Algorithm");
381 MODULE_AUTHOR("Sony Corporation");