deflate.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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 <jmorris@intercode.com.au>
  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. #include <crypto/internal/scompress.h>
  36. #define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION
  37. #define DEFLATE_DEF_WINBITS 11
  38. #define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL
  39. struct deflate_ctx {
  40. struct z_stream_s comp_stream;
  41. struct z_stream_s decomp_stream;
  42. };
  43. static int deflate_comp_init(struct deflate_ctx *ctx, int format)
  44. {
  45. int ret = 0;
  46. struct z_stream_s *stream = &ctx->comp_stream;
  47. stream->workspace = vzalloc(zlib_deflate_workspacesize(
  48. MAX_WBITS, MAX_MEM_LEVEL));
  49. if (!stream->workspace) {
  50. ret = -ENOMEM;
  51. goto out;
  52. }
  53. if (format)
  54. ret = zlib_deflateInit(stream, 3);
  55. else
  56. ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
  57. -DEFLATE_DEF_WINBITS,
  58. DEFLATE_DEF_MEMLEVEL,
  59. Z_DEFAULT_STRATEGY);
  60. if (ret != Z_OK) {
  61. ret = -EINVAL;
  62. goto out_free;
  63. }
  64. out:
  65. return ret;
  66. out_free:
  67. vfree(stream->workspace);
  68. goto out;
  69. }
  70. static int deflate_decomp_init(struct deflate_ctx *ctx, int format)
  71. {
  72. int ret = 0;
  73. struct z_stream_s *stream = &ctx->decomp_stream;
  74. stream->workspace = vzalloc(zlib_inflate_workspacesize());
  75. if (!stream->workspace) {
  76. ret = -ENOMEM;
  77. goto out;
  78. }
  79. if (format)
  80. ret = zlib_inflateInit(stream);
  81. else
  82. ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS);
  83. if (ret != Z_OK) {
  84. ret = -EINVAL;
  85. goto out_free;
  86. }
  87. out:
  88. return ret;
  89. out_free:
  90. vfree(stream->workspace);
  91. goto out;
  92. }
  93. static void deflate_comp_exit(struct deflate_ctx *ctx)
  94. {
  95. zlib_deflateEnd(&ctx->comp_stream);
  96. vfree(ctx->comp_stream.workspace);
  97. }
  98. static void deflate_decomp_exit(struct deflate_ctx *ctx)
  99. {
  100. zlib_inflateEnd(&ctx->decomp_stream);
  101. vfree(ctx->decomp_stream.workspace);
  102. }
  103. static int __deflate_init(void *ctx, int format)
  104. {
  105. int ret;
  106. ret = deflate_comp_init(ctx, format);
  107. if (ret)
  108. goto out;
  109. ret = deflate_decomp_init(ctx, format);
  110. if (ret)
  111. deflate_comp_exit(ctx);
  112. out:
  113. return ret;
  114. }
  115. static void *gen_deflate_alloc_ctx(struct crypto_scomp *tfm, int format)
  116. {
  117. struct deflate_ctx *ctx;
  118. int ret;
  119. ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
  120. if (!ctx)
  121. return ERR_PTR(-ENOMEM);
  122. ret = __deflate_init(ctx, format);
  123. if (ret) {
  124. kfree(ctx);
  125. return ERR_PTR(ret);
  126. }
  127. return ctx;
  128. }
  129. static void *deflate_alloc_ctx(struct crypto_scomp *tfm)
  130. {
  131. return gen_deflate_alloc_ctx(tfm, 0);
  132. }
  133. static void *zlib_deflate_alloc_ctx(struct crypto_scomp *tfm)
  134. {
  135. return gen_deflate_alloc_ctx(tfm, 1);
  136. }
  137. static int deflate_init(struct crypto_tfm *tfm)
  138. {
  139. struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
  140. return __deflate_init(ctx, 0);
  141. }
  142. static void __deflate_exit(void *ctx)
  143. {
  144. deflate_comp_exit(ctx);
  145. deflate_decomp_exit(ctx);
  146. }
  147. static void deflate_free_ctx(struct crypto_scomp *tfm, void *ctx)
  148. {
  149. __deflate_exit(ctx);
  150. kzfree(ctx);
  151. }
  152. static void deflate_exit(struct crypto_tfm *tfm)
  153. {
  154. struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
  155. __deflate_exit(ctx);
  156. }
  157. static int __deflate_compress(const u8 *src, unsigned int slen,
  158. u8 *dst, unsigned int *dlen, void *ctx)
  159. {
  160. int ret = 0;
  161. struct deflate_ctx *dctx = ctx;
  162. struct z_stream_s *stream = &dctx->comp_stream;
  163. ret = zlib_deflateReset(stream);
  164. if (ret != Z_OK) {
  165. ret = -EINVAL;
  166. goto out;
  167. }
  168. stream->next_in = (u8 *)src;
  169. stream->avail_in = slen;
  170. stream->next_out = (u8 *)dst;
  171. stream->avail_out = *dlen;
  172. ret = zlib_deflate(stream, Z_FINISH);
  173. if (ret != Z_STREAM_END) {
  174. ret = -EINVAL;
  175. goto out;
  176. }
  177. ret = 0;
  178. *dlen = stream->total_out;
  179. out:
  180. return ret;
  181. }
  182. static int deflate_compress(struct crypto_tfm *tfm, const u8 *src,
  183. unsigned int slen, u8 *dst, unsigned int *dlen)
  184. {
  185. struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
  186. return __deflate_compress(src, slen, dst, dlen, dctx);
  187. }
  188. static int deflate_scompress(struct crypto_scomp *tfm, const u8 *src,
  189. unsigned int slen, u8 *dst, unsigned int *dlen,
  190. void *ctx)
  191. {
  192. return __deflate_compress(src, slen, dst, dlen, ctx);
  193. }
  194. static int __deflate_decompress(const u8 *src, unsigned int slen,
  195. u8 *dst, unsigned int *dlen, void *ctx)
  196. {
  197. int ret = 0;
  198. struct deflate_ctx *dctx = ctx;
  199. struct z_stream_s *stream = &dctx->decomp_stream;
  200. ret = zlib_inflateReset(stream);
  201. if (ret != Z_OK) {
  202. ret = -EINVAL;
  203. goto out;
  204. }
  205. stream->next_in = (u8 *)src;
  206. stream->avail_in = slen;
  207. stream->next_out = (u8 *)dst;
  208. stream->avail_out = *dlen;
  209. ret = zlib_inflate(stream, Z_SYNC_FLUSH);
  210. /*
  211. * Work around a bug in zlib, which sometimes wants to taste an extra
  212. * byte when being used in the (undocumented) raw deflate mode.
  213. * (From USAGI).
  214. */
  215. if (ret == Z_OK && !stream->avail_in && stream->avail_out) {
  216. u8 zerostuff = 0;
  217. stream->next_in = &zerostuff;
  218. stream->avail_in = 1;
  219. ret = zlib_inflate(stream, Z_FINISH);
  220. }
  221. if (ret != Z_STREAM_END) {
  222. ret = -EINVAL;
  223. goto out;
  224. }
  225. ret = 0;
  226. *dlen = stream->total_out;
  227. out:
  228. return ret;
  229. }
  230. static int deflate_decompress(struct crypto_tfm *tfm, const u8 *src,
  231. unsigned int slen, u8 *dst, unsigned int *dlen)
  232. {
  233. struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
  234. return __deflate_decompress(src, slen, dst, dlen, dctx);
  235. }
  236. static int deflate_sdecompress(struct crypto_scomp *tfm, const u8 *src,
  237. unsigned int slen, u8 *dst, unsigned int *dlen,
  238. void *ctx)
  239. {
  240. return __deflate_decompress(src, slen, dst, dlen, ctx);
  241. }
  242. static struct crypto_alg alg = {
  243. .cra_name = "deflate",
  244. .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
  245. .cra_ctxsize = sizeof(struct deflate_ctx),
  246. .cra_module = THIS_MODULE,
  247. .cra_init = deflate_init,
  248. .cra_exit = deflate_exit,
  249. .cra_u = { .compress = {
  250. .coa_compress = deflate_compress,
  251. .coa_decompress = deflate_decompress } }
  252. };
  253. static struct scomp_alg scomp[] = { {
  254. .alloc_ctx = deflate_alloc_ctx,
  255. .free_ctx = deflate_free_ctx,
  256. .compress = deflate_scompress,
  257. .decompress = deflate_sdecompress,
  258. .base = {
  259. .cra_name = "deflate",
  260. .cra_driver_name = "deflate-scomp",
  261. .cra_module = THIS_MODULE,
  262. }
  263. }, {
  264. .alloc_ctx = zlib_deflate_alloc_ctx,
  265. .free_ctx = deflate_free_ctx,
  266. .compress = deflate_scompress,
  267. .decompress = deflate_sdecompress,
  268. .base = {
  269. .cra_name = "zlib-deflate",
  270. .cra_driver_name = "zlib-deflate-scomp",
  271. .cra_module = THIS_MODULE,
  272. }
  273. } };
  274. static int __init deflate_mod_init(void)
  275. {
  276. int ret;
  277. ret = crypto_register_alg(&alg);
  278. if (ret)
  279. return ret;
  280. ret = crypto_register_scomps(scomp, ARRAY_SIZE(scomp));
  281. if (ret) {
  282. crypto_unregister_alg(&alg);
  283. return ret;
  284. }
  285. return ret;
  286. }
  287. static void __exit deflate_mod_fini(void)
  288. {
  289. crypto_unregister_alg(&alg);
  290. crypto_unregister_scomps(scomp, ARRAY_SIZE(scomp));
  291. }
  292. module_init(deflate_mod_init);
  293. module_exit(deflate_mod_fini);
  294. MODULE_LICENSE("GPL");
  295. MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
  296. MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
  297. MODULE_ALIAS_CRYPTO("deflate");