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