zlib.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  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. #define pr_fmt(fmt) "%s: " fmt, __func__
  23. #include <linux/init.h>
  24. #include <linux/module.h>
  25. #include <linux/zlib.h>
  26. #include <linux/vmalloc.h>
  27. #include <linux/interrupt.h>
  28. #include <linux/mm.h>
  29. #include <linux/net.h>
  30. #include <crypto/internal/compress.h>
  31. #include <net/netlink.h>
  32. struct zlib_ctx {
  33. struct z_stream_s comp_stream;
  34. struct z_stream_s decomp_stream;
  35. int decomp_windowBits;
  36. };
  37. static void zlib_comp_exit(struct zlib_ctx *ctx)
  38. {
  39. struct z_stream_s *stream = &ctx->comp_stream;
  40. if (stream->workspace) {
  41. zlib_deflateEnd(stream);
  42. vfree(stream->workspace);
  43. stream->workspace = NULL;
  44. }
  45. }
  46. static void zlib_decomp_exit(struct zlib_ctx *ctx)
  47. {
  48. struct z_stream_s *stream = &ctx->decomp_stream;
  49. if (stream->workspace) {
  50. zlib_inflateEnd(stream);
  51. vfree(stream->workspace);
  52. stream->workspace = NULL;
  53. }
  54. }
  55. static int zlib_init(struct crypto_tfm *tfm)
  56. {
  57. return 0;
  58. }
  59. static void zlib_exit(struct crypto_tfm *tfm)
  60. {
  61. struct zlib_ctx *ctx = crypto_tfm_ctx(tfm);
  62. zlib_comp_exit(ctx);
  63. zlib_decomp_exit(ctx);
  64. }
  65. static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params,
  66. unsigned int len)
  67. {
  68. struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
  69. struct z_stream_s *stream = &ctx->comp_stream;
  70. struct nlattr *tb[ZLIB_COMP_MAX + 1];
  71. int window_bits, mem_level;
  72. size_t workspacesize;
  73. int ret;
  74. ret = nla_parse(tb, ZLIB_COMP_MAX, params, len, NULL);
  75. if (ret)
  76. return ret;
  77. zlib_comp_exit(ctx);
  78. window_bits = tb[ZLIB_COMP_WINDOWBITS]
  79. ? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS])
  80. : MAX_WBITS;
  81. mem_level = tb[ZLIB_COMP_MEMLEVEL]
  82. ? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL])
  83. : DEF_MEM_LEVEL;
  84. workspacesize = zlib_deflate_workspacesize(window_bits, mem_level);
  85. stream->workspace = vzalloc(workspacesize);
  86. if (!stream->workspace)
  87. return -ENOMEM;
  88. ret = zlib_deflateInit2(stream,
  89. tb[ZLIB_COMP_LEVEL]
  90. ? nla_get_u32(tb[ZLIB_COMP_LEVEL])
  91. : Z_DEFAULT_COMPRESSION,
  92. tb[ZLIB_COMP_METHOD]
  93. ? nla_get_u32(tb[ZLIB_COMP_METHOD])
  94. : Z_DEFLATED,
  95. window_bits,
  96. mem_level,
  97. tb[ZLIB_COMP_STRATEGY]
  98. ? nla_get_u32(tb[ZLIB_COMP_STRATEGY])
  99. : Z_DEFAULT_STRATEGY);
  100. if (ret != Z_OK) {
  101. vfree(stream->workspace);
  102. stream->workspace = NULL;
  103. return -EINVAL;
  104. }
  105. return 0;
  106. }
  107. static int zlib_compress_init(struct crypto_pcomp *tfm)
  108. {
  109. int ret;
  110. struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
  111. struct z_stream_s *stream = &dctx->comp_stream;
  112. ret = zlib_deflateReset(stream);
  113. if (ret != Z_OK)
  114. return -EINVAL;
  115. return 0;
  116. }
  117. static int zlib_compress_update(struct crypto_pcomp *tfm,
  118. struct comp_request *req)
  119. {
  120. int ret;
  121. struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
  122. struct z_stream_s *stream = &dctx->comp_stream;
  123. pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
  124. stream->next_in = req->next_in;
  125. stream->avail_in = req->avail_in;
  126. stream->next_out = req->next_out;
  127. stream->avail_out = req->avail_out;
  128. ret = zlib_deflate(stream, Z_NO_FLUSH);
  129. switch (ret) {
  130. case Z_OK:
  131. break;
  132. case Z_BUF_ERROR:
  133. pr_debug("zlib_deflate could not make progress\n");
  134. return -EAGAIN;
  135. default:
  136. pr_debug("zlib_deflate failed %d\n", ret);
  137. return -EINVAL;
  138. }
  139. ret = req->avail_out - stream->avail_out;
  140. pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
  141. stream->avail_in, stream->avail_out,
  142. req->avail_in - stream->avail_in, ret);
  143. req->next_in = stream->next_in;
  144. req->avail_in = stream->avail_in;
  145. req->next_out = stream->next_out;
  146. req->avail_out = stream->avail_out;
  147. return ret;
  148. }
  149. static int zlib_compress_final(struct crypto_pcomp *tfm,
  150. struct comp_request *req)
  151. {
  152. int ret;
  153. struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
  154. struct z_stream_s *stream = &dctx->comp_stream;
  155. pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
  156. stream->next_in = req->next_in;
  157. stream->avail_in = req->avail_in;
  158. stream->next_out = req->next_out;
  159. stream->avail_out = req->avail_out;
  160. ret = zlib_deflate(stream, Z_FINISH);
  161. if (ret != Z_STREAM_END) {
  162. pr_debug("zlib_deflate failed %d\n", ret);
  163. return -EINVAL;
  164. }
  165. ret = req->avail_out - stream->avail_out;
  166. pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
  167. stream->avail_in, stream->avail_out,
  168. req->avail_in - stream->avail_in, ret);
  169. req->next_in = stream->next_in;
  170. req->avail_in = stream->avail_in;
  171. req->next_out = stream->next_out;
  172. req->avail_out = stream->avail_out;
  173. return ret;
  174. }
  175. static int zlib_decompress_setup(struct crypto_pcomp *tfm, void *params,
  176. unsigned int len)
  177. {
  178. struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
  179. struct z_stream_s *stream = &ctx->decomp_stream;
  180. struct nlattr *tb[ZLIB_DECOMP_MAX + 1];
  181. int ret = 0;
  182. ret = nla_parse(tb, ZLIB_DECOMP_MAX, params, len, NULL);
  183. if (ret)
  184. return ret;
  185. zlib_decomp_exit(ctx);
  186. ctx->decomp_windowBits = tb[ZLIB_DECOMP_WINDOWBITS]
  187. ? nla_get_u32(tb[ZLIB_DECOMP_WINDOWBITS])
  188. : DEF_WBITS;
  189. stream->workspace = vzalloc(zlib_inflate_workspacesize());
  190. if (!stream->workspace)
  191. return -ENOMEM;
  192. ret = zlib_inflateInit2(stream, ctx->decomp_windowBits);
  193. if (ret != Z_OK) {
  194. vfree(stream->workspace);
  195. stream->workspace = NULL;
  196. return -EINVAL;
  197. }
  198. return 0;
  199. }
  200. static int zlib_decompress_init(struct crypto_pcomp *tfm)
  201. {
  202. int ret;
  203. struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
  204. struct z_stream_s *stream = &dctx->decomp_stream;
  205. ret = zlib_inflateReset(stream);
  206. if (ret != Z_OK)
  207. return -EINVAL;
  208. return 0;
  209. }
  210. static int zlib_decompress_update(struct crypto_pcomp *tfm,
  211. struct comp_request *req)
  212. {
  213. int ret;
  214. struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
  215. struct z_stream_s *stream = &dctx->decomp_stream;
  216. pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
  217. stream->next_in = req->next_in;
  218. stream->avail_in = req->avail_in;
  219. stream->next_out = req->next_out;
  220. stream->avail_out = req->avail_out;
  221. ret = zlib_inflate(stream, Z_SYNC_FLUSH);
  222. switch (ret) {
  223. case Z_OK:
  224. case Z_STREAM_END:
  225. break;
  226. case Z_BUF_ERROR:
  227. pr_debug("zlib_inflate could not make progress\n");
  228. return -EAGAIN;
  229. default:
  230. pr_debug("zlib_inflate failed %d\n", ret);
  231. return -EINVAL;
  232. }
  233. ret = req->avail_out - stream->avail_out;
  234. pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
  235. stream->avail_in, stream->avail_out,
  236. req->avail_in - stream->avail_in, ret);
  237. req->next_in = stream->next_in;
  238. req->avail_in = stream->avail_in;
  239. req->next_out = stream->next_out;
  240. req->avail_out = stream->avail_out;
  241. return ret;
  242. }
  243. static int zlib_decompress_final(struct crypto_pcomp *tfm,
  244. struct comp_request *req)
  245. {
  246. int ret;
  247. struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
  248. struct z_stream_s *stream = &dctx->decomp_stream;
  249. pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
  250. stream->next_in = req->next_in;
  251. stream->avail_in = req->avail_in;
  252. stream->next_out = req->next_out;
  253. stream->avail_out = req->avail_out;
  254. if (dctx->decomp_windowBits < 0) {
  255. ret = zlib_inflate(stream, Z_SYNC_FLUSH);
  256. /*
  257. * Work around a bug in zlib, which sometimes wants to taste an
  258. * extra byte when being used in the (undocumented) raw deflate
  259. * mode. (From USAGI).
  260. */
  261. if (ret == Z_OK && !stream->avail_in && stream->avail_out) {
  262. const void *saved_next_in = stream->next_in;
  263. u8 zerostuff = 0;
  264. stream->next_in = &zerostuff;
  265. stream->avail_in = 1;
  266. ret = zlib_inflate(stream, Z_FINISH);
  267. stream->next_in = saved_next_in;
  268. stream->avail_in = 0;
  269. }
  270. } else
  271. ret = zlib_inflate(stream, Z_FINISH);
  272. if (ret != Z_STREAM_END) {
  273. pr_debug("zlib_inflate failed %d\n", ret);
  274. return -EINVAL;
  275. }
  276. ret = req->avail_out - stream->avail_out;
  277. pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
  278. stream->avail_in, stream->avail_out,
  279. req->avail_in - stream->avail_in, ret);
  280. req->next_in = stream->next_in;
  281. req->avail_in = stream->avail_in;
  282. req->next_out = stream->next_out;
  283. req->avail_out = stream->avail_out;
  284. return ret;
  285. }
  286. static struct pcomp_alg zlib_alg = {
  287. .compress_setup = zlib_compress_setup,
  288. .compress_init = zlib_compress_init,
  289. .compress_update = zlib_compress_update,
  290. .compress_final = zlib_compress_final,
  291. .decompress_setup = zlib_decompress_setup,
  292. .decompress_init = zlib_decompress_init,
  293. .decompress_update = zlib_decompress_update,
  294. .decompress_final = zlib_decompress_final,
  295. .base = {
  296. .cra_name = "zlib",
  297. .cra_flags = CRYPTO_ALG_TYPE_PCOMPRESS,
  298. .cra_ctxsize = sizeof(struct zlib_ctx),
  299. .cra_module = THIS_MODULE,
  300. .cra_init = zlib_init,
  301. .cra_exit = zlib_exit,
  302. }
  303. };
  304. static int __init zlib_mod_init(void)
  305. {
  306. return crypto_register_pcomp(&zlib_alg);
  307. }
  308. static void __exit zlib_mod_fini(void)
  309. {
  310. crypto_unregister_pcomp(&zlib_alg);
  311. }
  312. module_init(zlib_mod_init);
  313. module_exit(zlib_mod_fini);
  314. MODULE_LICENSE("GPL");
  315. MODULE_DESCRIPTION("Zlib Compression Algorithm");
  316. MODULE_AUTHOR("Sony Corporation");