zlib.c 9.5 KB

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