3 #define pr_fmt(fmt) "%s: " fmt, __func__
5 #include <linux/init.h>
6 #include <linux/module.h>
7 #include <linux/zlib.h>
8 #include <linux/vmalloc.h>
9 #include <linux/interrupt.h>
11 #include <linux/net.h>
12 #include <linux/slab.h>
14 #include <crypto/internal/compress.h>
16 #include <net/netlink.h>
20 struct z_stream_s comp_stream
;
21 struct z_stream_s decomp_stream
;
22 int decomp_windowBits
;
26 static void zlib_comp_exit(struct zlib_ctx
*ctx
)
28 struct z_stream_s
*stream
= &ctx
->comp_stream
;
30 if (stream
->workspace
) {
31 zlib_deflateEnd(stream
);
32 vfree(stream
->workspace
);
33 stream
->workspace
= NULL
;
37 static void zlib_decomp_exit(struct zlib_ctx
*ctx
)
39 struct z_stream_s
*stream
= &ctx
->decomp_stream
;
41 if (stream
->workspace
) {
42 zlib_inflateEnd(stream
);
43 kfree(stream
->workspace
);
44 stream
->workspace
= NULL
;
48 static int zlib_init(struct crypto_tfm
*tfm
)
53 static void zlib_exit(struct crypto_tfm
*tfm
)
55 struct zlib_ctx
*ctx
= crypto_tfm_ctx(tfm
);
58 zlib_decomp_exit(ctx
);
62 static int zlib_compress_setup(struct crypto_pcomp
*tfm
, void *params
,
65 struct zlib_ctx
*ctx
= crypto_tfm_ctx(crypto_pcomp_tfm(tfm
));
66 struct z_stream_s
*stream
= &ctx
->comp_stream
;
67 struct nlattr
*tb
[ZLIB_COMP_MAX
+ 1];
71 ret
= nla_parse(tb
, ZLIB_COMP_MAX
, params
, len
, NULL
);
77 workspacesize
= zlib_deflate_workspacesize();
78 stream
->workspace
= vmalloc(workspacesize
);
79 if (!stream
->workspace
)
82 memset(stream
->workspace
, 0, workspacesize
);
83 ret
= zlib_deflateInit2(stream
,
85 ? nla_get_u32(tb
[ZLIB_COMP_LEVEL
])
86 : Z_DEFAULT_COMPRESSION
,
88 ? nla_get_u32(tb
[ZLIB_COMP_METHOD
])
90 tb
[ZLIB_COMP_WINDOWBITS
]
91 ? nla_get_u32(tb
[ZLIB_COMP_WINDOWBITS
])
93 tb
[ZLIB_COMP_MEMLEVEL
]
94 ? nla_get_u32(tb
[ZLIB_COMP_MEMLEVEL
])
96 tb
[ZLIB_COMP_STRATEGY
]
97 ? nla_get_u32(tb
[ZLIB_COMP_STRATEGY
])
98 : Z_DEFAULT_STRATEGY
);
100 vfree(stream
->workspace
);
101 stream
->workspace
= NULL
;
108 static int zlib_compress_init(struct crypto_pcomp
*tfm
)
111 struct zlib_ctx
*dctx
= crypto_tfm_ctx(crypto_pcomp_tfm(tfm
));
112 struct z_stream_s
*stream
= &dctx
->comp_stream
;
114 ret
= zlib_deflateReset(stream
);
121 static int zlib_compress_update(struct crypto_pcomp
*tfm
,
122 struct comp_request
*req
)
125 struct zlib_ctx
*dctx
= crypto_tfm_ctx(crypto_pcomp_tfm(tfm
));
126 struct z_stream_s
*stream
= &dctx
->comp_stream
;
128 pr_debug("avail_in %u, avail_out %u\n", req
->avail_in
, req
->avail_out
);
129 stream
->next_in
= req
->next_in
;
130 stream
->avail_in
= req
->avail_in
;
131 stream
->next_out
= req
->next_out
;
132 stream
->avail_out
= req
->avail_out
;
134 ret
= zlib_deflate(stream
, Z_NO_FLUSH
);
140 pr_debug("zlib_deflate could not make progress\n");
144 pr_debug("zlib_deflate failed %d\n", ret
);
148 ret
= req
->avail_out
- stream
->avail_out
;
149 pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
150 stream
->avail_in
, stream
->avail_out
,
151 req
->avail_in
- stream
->avail_in
, ret
);
152 req
->next_in
= stream
->next_in
;
153 req
->avail_in
= stream
->avail_in
;
154 req
->next_out
= stream
->next_out
;
155 req
->avail_out
= stream
->avail_out
;
159 static int zlib_compress_final(struct crypto_pcomp
*tfm
,
160 struct comp_request
*req
)
163 struct zlib_ctx
*dctx
= crypto_tfm_ctx(crypto_pcomp_tfm(tfm
));
164 struct z_stream_s
*stream
= &dctx
->comp_stream
;
166 pr_debug("avail_in %u, avail_out %u\n", req
->avail_in
, req
->avail_out
);
167 stream
->next_in
= req
->next_in
;
168 stream
->avail_in
= req
->avail_in
;
169 stream
->next_out
= req
->next_out
;
170 stream
->avail_out
= req
->avail_out
;
172 ret
= zlib_deflate(stream
, Z_FINISH
);
173 if (ret
!= Z_STREAM_END
) {
174 pr_debug("zlib_deflate failed %d\n", ret
);
178 ret
= req
->avail_out
- stream
->avail_out
;
179 pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
180 stream
->avail_in
, stream
->avail_out
,
181 req
->avail_in
- stream
->avail_in
, ret
);
182 req
->next_in
= stream
->next_in
;
183 req
->avail_in
= stream
->avail_in
;
184 req
->next_out
= stream
->next_out
;
185 req
->avail_out
= stream
->avail_out
;
190 static int zlib_decompress_setup(struct crypto_pcomp
*tfm
, void *params
,
193 struct zlib_ctx
*ctx
= crypto_tfm_ctx(crypto_pcomp_tfm(tfm
));
194 struct z_stream_s
*stream
= &ctx
->decomp_stream
;
195 struct nlattr
*tb
[ZLIB_DECOMP_MAX
+ 1];
198 ret
= nla_parse(tb
, ZLIB_DECOMP_MAX
, params
, len
, NULL
);
202 zlib_decomp_exit(ctx
);
204 ctx
->decomp_windowBits
= tb
[ZLIB_DECOMP_WINDOWBITS
]
205 ? nla_get_u32(tb
[ZLIB_DECOMP_WINDOWBITS
])
208 stream
->workspace
= kzalloc(zlib_inflate_workspacesize(), GFP_KERNEL
);
209 if (!stream
->workspace
)
212 ret
= zlib_inflateInit2(stream
, ctx
->decomp_windowBits
);
214 kfree(stream
->workspace
);
215 stream
->workspace
= NULL
;
222 static int zlib_decompress_init(struct crypto_pcomp
*tfm
)
225 struct zlib_ctx
*dctx
= crypto_tfm_ctx(crypto_pcomp_tfm(tfm
));
226 struct z_stream_s
*stream
= &dctx
->decomp_stream
;
228 ret
= zlib_inflateReset(stream
);
235 static int zlib_decompress_update(struct crypto_pcomp
*tfm
,
236 struct comp_request
*req
)
239 struct zlib_ctx
*dctx
= crypto_tfm_ctx(crypto_pcomp_tfm(tfm
));
240 struct z_stream_s
*stream
= &dctx
->decomp_stream
;
242 pr_debug("avail_in %u, avail_out %u\n", req
->avail_in
, req
->avail_out
);
243 stream
->next_in
= req
->next_in
;
244 stream
->avail_in
= req
->avail_in
;
245 stream
->next_out
= req
->next_out
;
246 stream
->avail_out
= req
->avail_out
;
248 ret
= zlib_inflate(stream
, Z_SYNC_FLUSH
);
255 pr_debug("zlib_inflate could not make progress\n");
259 pr_debug("zlib_inflate failed %d\n", ret
);
263 ret
= req
->avail_out
- stream
->avail_out
;
264 pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
265 stream
->avail_in
, stream
->avail_out
,
266 req
->avail_in
- stream
->avail_in
, ret
);
267 req
->next_in
= stream
->next_in
;
268 req
->avail_in
= stream
->avail_in
;
269 req
->next_out
= stream
->next_out
;
270 req
->avail_out
= stream
->avail_out
;
274 static int zlib_decompress_final(struct crypto_pcomp
*tfm
,
275 struct comp_request
*req
)
278 struct zlib_ctx
*dctx
= crypto_tfm_ctx(crypto_pcomp_tfm(tfm
));
279 struct z_stream_s
*stream
= &dctx
->decomp_stream
;
281 pr_debug("avail_in %u, avail_out %u\n", req
->avail_in
, req
->avail_out
);
282 stream
->next_in
= req
->next_in
;
283 stream
->avail_in
= req
->avail_in
;
284 stream
->next_out
= req
->next_out
;
285 stream
->avail_out
= req
->avail_out
;
287 if (dctx
->decomp_windowBits
< 0) {
288 ret
= zlib_inflate(stream
, Z_SYNC_FLUSH
);
289 if (ret
== Z_OK
&& !stream
->avail_in
&& stream
->avail_out
) {
290 const void *saved_next_in
= stream
->next_in
;
293 stream
->next_in
= &zerostuff
;
294 stream
->avail_in
= 1;
295 ret
= zlib_inflate(stream
, Z_FINISH
);
296 stream
->next_in
= saved_next_in
;
297 stream
->avail_in
= 0;
300 ret
= zlib_inflate(stream
, Z_FINISH
);
301 if (ret
!= Z_STREAM_END
) {
302 pr_debug("zlib_inflate failed %d\n", ret
);
306 ret
= req
->avail_out
- stream
->avail_out
;
307 pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
308 stream
->avail_in
, stream
->avail_out
,
309 req
->avail_in
- stream
->avail_in
, ret
);
310 req
->next_in
= stream
->next_in
;
311 req
->avail_in
= stream
->avail_in
;
312 req
->next_out
= stream
->next_out
;
313 req
->avail_out
= stream
->avail_out
;
318 static struct pcomp_alg zlib_alg
= {
319 .compress_setup
= zlib_compress_setup
,
320 .compress_init
= zlib_compress_init
,
321 .compress_update
= zlib_compress_update
,
322 .compress_final
= zlib_compress_final
,
323 .decompress_setup
= zlib_decompress_setup
,
324 .decompress_init
= zlib_decompress_init
,
325 .decompress_update
= zlib_decompress_update
,
326 .decompress_final
= zlib_decompress_final
,
330 .cra_flags
= CRYPTO_ALG_TYPE_PCOMPRESS
,
331 .cra_ctxsize
= sizeof(struct zlib_ctx
),
332 .cra_module
= THIS_MODULE
,
333 .cra_init
= zlib_init
,
334 .cra_exit
= zlib_exit
,
338 static int __init
zlib_mod_init(void)
340 return crypto_register_pcomp(&zlib_alg
);
343 static void __exit
zlib_mod_fini(void)
345 crypto_unregister_pcomp(&zlib_alg
);
348 module_init(zlib_mod_init
);
349 module_exit(zlib_mod_fini
);
351 MODULE_LICENSE("GPL");
352 MODULE_DESCRIPTION("Zlib Compression Algorithm");
353 MODULE_AUTHOR("Sony Corporation");