Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
deflate.c
Go to the documentation of this file.
1 /*
2  * Cryptographic API.
3  *
4  * Deflate algorithm (RFC 1951), implemented here primarily for use
5  * by IPCOMP (RFC 3173 & RFC 2394).
6  *
7  * Copyright (c) 2003 James Morris <[email protected]>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by the Free
11  * Software Foundation; either version 2 of the License, or (at your option)
12  * any later version.
13  *
14  * FIXME: deflate transforms will require up to a total of about 436k of kernel
15  * memory on i386 (390k for compression, the rest for decompression), as the
16  * current zlib kernel code uses a worst case pre-allocation system by default.
17  * This needs to be fixed so that the amount of memory required is properly
18  * related to the winbits and memlevel parameters.
19  *
20  * The default winbits of 11 should suit most packets, and it may be something
21  * to configure on a per-tfm basis in the future.
22  *
23  * Currently, compression history is not maintained between tfm calls, as
24  * it is not needed for IPCOMP and keeps the code simpler. It can be
25  * implemented if someone wants it.
26  */
27 #include <linux/init.h>
28 #include <linux/module.h>
29 #include <linux/crypto.h>
30 #include <linux/zlib.h>
31 #include <linux/vmalloc.h>
32 #include <linux/interrupt.h>
33 #include <linux/mm.h>
34 #include <linux/net.h>
35 
36 #define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION
37 #define DEFLATE_DEF_WINBITS 11
38 #define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL
39 
40 struct deflate_ctx {
43 };
44 
45 static int deflate_comp_init(struct deflate_ctx *ctx)
46 {
47  int ret = 0;
48  struct z_stream_s *stream = &ctx->comp_stream;
49 
52  if (!stream->workspace) {
53  ret = -ENOMEM;
54  goto out;
55  }
59  if (ret != Z_OK) {
60  ret = -EINVAL;
61  goto out_free;
62  }
63 out:
64  return ret;
65 out_free:
66  vfree(stream->workspace);
67  goto out;
68 }
69 
70 static int deflate_decomp_init(struct deflate_ctx *ctx)
71 {
72  int ret = 0;
73  struct z_stream_s *stream = &ctx->decomp_stream;
74 
76  if (!stream->workspace) {
77  ret = -ENOMEM;
78  goto out;
79  }
80  ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS);
81  if (ret != Z_OK) {
82  ret = -EINVAL;
83  goto out_free;
84  }
85 out:
86  return ret;
87 out_free:
88  vfree(stream->workspace);
89  goto out;
90 }
91 
92 static void deflate_comp_exit(struct deflate_ctx *ctx)
93 {
95  vfree(ctx->comp_stream.workspace);
96 }
97 
98 static void deflate_decomp_exit(struct deflate_ctx *ctx)
99 {
101  vfree(ctx->decomp_stream.workspace);
102 }
103 
104 static int deflate_init(struct crypto_tfm *tfm)
105 {
106  struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
107  int ret;
108 
109  ret = deflate_comp_init(ctx);
110  if (ret)
111  goto out;
112  ret = deflate_decomp_init(ctx);
113  if (ret)
114  deflate_comp_exit(ctx);
115 out:
116  return ret;
117 }
118 
119 static void deflate_exit(struct crypto_tfm *tfm)
120 {
121  struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
122 
123  deflate_comp_exit(ctx);
124  deflate_decomp_exit(ctx);
125 }
126 
127 static int deflate_compress(struct crypto_tfm *tfm, const u8 *src,
128  unsigned int slen, u8 *dst, unsigned int *dlen)
129 {
130  int ret = 0;
131  struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
132  struct z_stream_s *stream = &dctx->comp_stream;
133 
134  ret = zlib_deflateReset(stream);
135  if (ret != Z_OK) {
136  ret = -EINVAL;
137  goto out;
138  }
139 
140  stream->next_in = (u8 *)src;
141  stream->avail_in = slen;
142  stream->next_out = (u8 *)dst;
143  stream->avail_out = *dlen;
144 
145  ret = zlib_deflate(stream, Z_FINISH);
146  if (ret != Z_STREAM_END) {
147  ret = -EINVAL;
148  goto out;
149  }
150  ret = 0;
151  *dlen = stream->total_out;
152 out:
153  return ret;
154 }
155 
156 static int deflate_decompress(struct crypto_tfm *tfm, const u8 *src,
157  unsigned int slen, u8 *dst, unsigned int *dlen)
158 {
159 
160  int ret = 0;
161  struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
162  struct z_stream_s *stream = &dctx->decomp_stream;
163 
164  ret = zlib_inflateReset(stream);
165  if (ret != Z_OK) {
166  ret = -EINVAL;
167  goto out;
168  }
169 
170  stream->next_in = (u8 *)src;
171  stream->avail_in = slen;
172  stream->next_out = (u8 *)dst;
173  stream->avail_out = *dlen;
174 
175  ret = zlib_inflate(stream, Z_SYNC_FLUSH);
176  /*
177  * Work around a bug in zlib, which sometimes wants to taste an extra
178  * byte when being used in the (undocumented) raw deflate mode.
179  * (From USAGI).
180  */
181  if (ret == Z_OK && !stream->avail_in && stream->avail_out) {
182  u8 zerostuff = 0;
183  stream->next_in = &zerostuff;
184  stream->avail_in = 1;
185  ret = zlib_inflate(stream, Z_FINISH);
186  }
187  if (ret != Z_STREAM_END) {
188  ret = -EINVAL;
189  goto out;
190  }
191  ret = 0;
192  *dlen = stream->total_out;
193 out:
194  return ret;
195 }
196 
197 static struct crypto_alg alg = {
198  .cra_name = "deflate",
199  .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
200  .cra_ctxsize = sizeof(struct deflate_ctx),
201  .cra_module = THIS_MODULE,
202  .cra_init = deflate_init,
203  .cra_exit = deflate_exit,
204  .cra_u = { .compress = {
205  .coa_compress = deflate_compress,
206  .coa_decompress = deflate_decompress } }
207 };
208 
209 static int __init deflate_mod_init(void)
210 {
211  return crypto_register_alg(&alg);
212 }
213 
214 static void __exit deflate_mod_fini(void)
215 {
216  crypto_unregister_alg(&alg);
217 }
218 
219 module_init(deflate_mod_init);
220 module_exit(deflate_mod_fini);
221 
222 MODULE_LICENSE("GPL");
223 MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
224 MODULE_AUTHOR("James Morris <[email protected]>");
225