2 #include <linux/init.h>
3 #include <linux/module.h>
4 #include <linux/crypto.h>
5 #include <linux/zlib.h>
6 #include <linux/vmalloc.h>
7 #include <linux/interrupt.h>
10 #include <linux/slab.h>
12 #define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION
13 #define DEFLATE_DEF_WINBITS 11
14 #define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL
17 struct z_stream_s comp_stream
;
18 struct z_stream_s decomp_stream
;
21 static int deflate_comp_init(struct deflate_ctx
*ctx
)
24 struct z_stream_s
*stream
= &ctx
->comp_stream
;
26 stream
->workspace
= vmalloc(zlib_deflate_workspacesize());
27 if (!stream
->workspace
) {
31 memset(stream
->workspace
, 0, zlib_deflate_workspacesize());
32 ret
= zlib_deflateInit2(stream
, DEFLATE_DEF_LEVEL
, Z_DEFLATED
,
33 -DEFLATE_DEF_WINBITS
, DEFLATE_DEF_MEMLEVEL
,
42 vfree(stream
->workspace
);
46 static int deflate_decomp_init(struct deflate_ctx
*ctx
)
49 struct z_stream_s
*stream
= &ctx
->decomp_stream
;
51 stream
->workspace
= kzalloc(zlib_inflate_workspacesize(), GFP_KERNEL
);
52 if (!stream
->workspace
) {
56 ret
= zlib_inflateInit2(stream
, -DEFLATE_DEF_WINBITS
);
64 kfree(stream
->workspace
);
68 static void deflate_comp_exit(struct deflate_ctx
*ctx
)
70 zlib_deflateEnd(&ctx
->comp_stream
);
71 vfree(ctx
->comp_stream
.workspace
);
74 static void deflate_decomp_exit(struct deflate_ctx
*ctx
)
76 zlib_inflateEnd(&ctx
->decomp_stream
);
77 kfree(ctx
->decomp_stream
.workspace
);
80 static int deflate_init(struct crypto_tfm
*tfm
)
82 struct deflate_ctx
*ctx
= crypto_tfm_ctx(tfm
);
85 ret
= deflate_comp_init(ctx
);
88 ret
= deflate_decomp_init(ctx
);
90 deflate_comp_exit(ctx
);
95 static void deflate_exit(struct crypto_tfm
*tfm
)
97 struct deflate_ctx
*ctx
= crypto_tfm_ctx(tfm
);
99 deflate_comp_exit(ctx
);
100 deflate_decomp_exit(ctx
);
103 static int deflate_compress(struct crypto_tfm
*tfm
, const u8
*src
,
104 unsigned int slen
, u8
*dst
, unsigned int *dlen
)
107 struct deflate_ctx
*dctx
= crypto_tfm_ctx(tfm
);
108 struct z_stream_s
*stream
= &dctx
->comp_stream
;
110 ret
= zlib_deflateReset(stream
);
116 stream
->next_in
= (u8
*)src
;
117 stream
->avail_in
= slen
;
118 stream
->next_out
= (u8
*)dst
;
119 stream
->avail_out
= *dlen
;
121 ret
= zlib_deflate(stream
, Z_FINISH
);
122 if (ret
!= Z_STREAM_END
) {
127 *dlen
= stream
->total_out
;
132 static int deflate_decompress(struct crypto_tfm
*tfm
, const u8
*src
,
133 unsigned int slen
, u8
*dst
, unsigned int *dlen
)
137 struct deflate_ctx
*dctx
= crypto_tfm_ctx(tfm
);
138 struct z_stream_s
*stream
= &dctx
->decomp_stream
;
140 ret
= zlib_inflateReset(stream
);
146 stream
->next_in
= (u8
*)src
;
147 stream
->avail_in
= slen
;
148 stream
->next_out
= (u8
*)dst
;
149 stream
->avail_out
= *dlen
;
151 ret
= zlib_inflate(stream
, Z_SYNC_FLUSH
);
152 if (ret
== Z_OK
&& !stream
->avail_in
&& stream
->avail_out
) {
154 stream
->next_in
= &zerostuff
;
155 stream
->avail_in
= 1;
156 ret
= zlib_inflate(stream
, Z_FINISH
);
158 if (ret
!= Z_STREAM_END
) {
163 *dlen
= stream
->total_out
;
168 static struct crypto_alg alg
= {
169 .cra_name
= "deflate",
170 .cra_flags
= CRYPTO_ALG_TYPE_COMPRESS
,
171 .cra_ctxsize
= sizeof(struct deflate_ctx
),
172 .cra_module
= THIS_MODULE
,
173 .cra_list
= LIST_HEAD_INIT(alg
.cra_list
),
174 .cra_init
= deflate_init
,
175 .cra_exit
= deflate_exit
,
176 .cra_u
= { .compress
= {
177 .coa_compress
= deflate_compress
,
178 .coa_decompress
= deflate_decompress
} }
181 static int __init
deflate_mod_init(void)
183 return crypto_register_alg(&alg
);
186 static void __exit
deflate_mod_fini(void)
188 crypto_unregister_alg(&alg
);
191 module_init(deflate_mod_init
);
192 module_exit(deflate_mod_fini
);
194 MODULE_LICENSE("GPL");
195 MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
196 MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");