deflate.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Cryptographic API.
  4. *
  5. * Deflate algorithm (RFC 1951), implemented here primarily for use
  6. * by IPCOMP (RFC 3173 & RFC 2394).
  7. *
  8. * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
  9. * Copyright (c) 2023 Google, LLC. <ardb@kernel.org>
  10. * Copyright (c) 2025 Herbert Xu <herbert@gondor.apana.org.au>
  11. */
  12. #include <crypto/internal/acompress.h>
  13. #include <crypto/scatterwalk.h>
  14. #include <linux/init.h>
  15. #include <linux/kernel.h>
  16. #include <linux/module.h>
  17. #include <linux/mutex.h>
  18. #include <linux/overflow.h>
  19. #include <linux/percpu.h>
  20. #include <linux/scatterlist.h>
  21. #include <linux/slab.h>
  22. #include <linux/spinlock.h>
  23. #include <linux/zlib.h>
  24. #define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION
  25. #define DEFLATE_DEF_WINBITS 11
  26. #define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL
  27. struct deflate_stream {
  28. struct z_stream_s stream;
  29. u8 workspace[];
  30. };
  31. static DEFINE_MUTEX(deflate_stream_lock);
  32. static void *deflate_alloc_stream(void)
  33. {
  34. size_t size = max(zlib_inflate_workspacesize(),
  35. zlib_deflate_workspacesize(-DEFLATE_DEF_WINBITS,
  36. DEFLATE_DEF_MEMLEVEL));
  37. struct deflate_stream *ctx;
  38. ctx = kvmalloc_flex(*ctx, workspace, size);
  39. if (!ctx)
  40. return ERR_PTR(-ENOMEM);
  41. ctx->stream.workspace = ctx->workspace;
  42. return ctx;
  43. }
  44. static void deflate_free_stream(void *ctx)
  45. {
  46. kvfree(ctx);
  47. }
  48. static struct crypto_acomp_streams deflate_streams = {
  49. .alloc_ctx = deflate_alloc_stream,
  50. .free_ctx = deflate_free_stream,
  51. };
  52. static int deflate_compress_one(struct acomp_req *req,
  53. struct deflate_stream *ds)
  54. {
  55. struct z_stream_s *stream = &ds->stream;
  56. struct acomp_walk walk;
  57. int ret;
  58. ret = acomp_walk_virt(&walk, req, true);
  59. if (ret)
  60. return ret;
  61. do {
  62. unsigned int dcur;
  63. dcur = acomp_walk_next_dst(&walk);
  64. if (!dcur)
  65. return -ENOSPC;
  66. stream->avail_out = dcur;
  67. stream->next_out = walk.dst.virt.addr;
  68. do {
  69. int flush = Z_FINISH;
  70. unsigned int scur;
  71. stream->avail_in = 0;
  72. stream->next_in = NULL;
  73. scur = acomp_walk_next_src(&walk);
  74. if (scur) {
  75. if (acomp_walk_more_src(&walk, scur))
  76. flush = Z_NO_FLUSH;
  77. stream->avail_in = scur;
  78. stream->next_in = walk.src.virt.addr;
  79. }
  80. ret = zlib_deflate(stream, flush);
  81. if (scur) {
  82. scur -= stream->avail_in;
  83. acomp_walk_done_src(&walk, scur);
  84. }
  85. } while (ret == Z_OK && stream->avail_out);
  86. acomp_walk_done_dst(&walk, dcur);
  87. } while (ret == Z_OK);
  88. if (ret != Z_STREAM_END)
  89. return -EINVAL;
  90. req->dlen = stream->total_out;
  91. return 0;
  92. }
  93. static int deflate_compress(struct acomp_req *req)
  94. {
  95. struct crypto_acomp_stream *s;
  96. struct deflate_stream *ds;
  97. int err;
  98. s = crypto_acomp_lock_stream_bh(&deflate_streams);
  99. ds = s->ctx;
  100. err = zlib_deflateInit2(&ds->stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
  101. -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
  102. Z_DEFAULT_STRATEGY);
  103. if (err != Z_OK) {
  104. err = -EINVAL;
  105. goto out;
  106. }
  107. err = deflate_compress_one(req, ds);
  108. out:
  109. crypto_acomp_unlock_stream_bh(s);
  110. return err;
  111. }
  112. static int deflate_decompress_one(struct acomp_req *req,
  113. struct deflate_stream *ds)
  114. {
  115. struct z_stream_s *stream = &ds->stream;
  116. bool out_of_space = false;
  117. struct acomp_walk walk;
  118. int ret;
  119. ret = acomp_walk_virt(&walk, req, true);
  120. if (ret)
  121. return ret;
  122. do {
  123. unsigned int scur;
  124. stream->avail_in = 0;
  125. stream->next_in = NULL;
  126. scur = acomp_walk_next_src(&walk);
  127. if (scur) {
  128. stream->avail_in = scur;
  129. stream->next_in = walk.src.virt.addr;
  130. }
  131. do {
  132. unsigned int dcur;
  133. unsigned long avail_in;
  134. dcur = acomp_walk_next_dst(&walk);
  135. stream->avail_out = dcur;
  136. stream->next_out = walk.dst.virt.addr;
  137. avail_in = stream->avail_in;
  138. ret = zlib_inflate(stream, Z_NO_FLUSH);
  139. if (!dcur && avail_in == stream->avail_in) {
  140. out_of_space = true;
  141. break;
  142. }
  143. dcur -= stream->avail_out;
  144. acomp_walk_done_dst(&walk, dcur);
  145. } while (ret == Z_OK && stream->avail_in);
  146. if (scur)
  147. acomp_walk_done_src(&walk, scur);
  148. if (out_of_space)
  149. return -ENOSPC;
  150. } while (ret == Z_OK);
  151. if (ret != Z_STREAM_END)
  152. return -EINVAL;
  153. req->dlen = stream->total_out;
  154. return 0;
  155. }
  156. static int deflate_decompress(struct acomp_req *req)
  157. {
  158. struct crypto_acomp_stream *s;
  159. struct deflate_stream *ds;
  160. int err;
  161. s = crypto_acomp_lock_stream_bh(&deflate_streams);
  162. ds = s->ctx;
  163. err = zlib_inflateInit2(&ds->stream, -DEFLATE_DEF_WINBITS);
  164. if (err != Z_OK) {
  165. err = -EINVAL;
  166. goto out;
  167. }
  168. err = deflate_decompress_one(req, ds);
  169. out:
  170. crypto_acomp_unlock_stream_bh(s);
  171. return err;
  172. }
  173. static int deflate_init(struct crypto_acomp *tfm)
  174. {
  175. int ret;
  176. mutex_lock(&deflate_stream_lock);
  177. ret = crypto_acomp_alloc_streams(&deflate_streams);
  178. mutex_unlock(&deflate_stream_lock);
  179. return ret;
  180. }
  181. static struct acomp_alg acomp = {
  182. .compress = deflate_compress,
  183. .decompress = deflate_decompress,
  184. .init = deflate_init,
  185. .base.cra_name = "deflate",
  186. .base.cra_driver_name = "deflate-generic",
  187. .base.cra_flags = CRYPTO_ALG_REQ_VIRT,
  188. .base.cra_module = THIS_MODULE,
  189. };
  190. static int __init deflate_mod_init(void)
  191. {
  192. return crypto_register_acomp(&acomp);
  193. }
  194. static void __exit deflate_mod_fini(void)
  195. {
  196. crypto_unregister_acomp(&acomp);
  197. crypto_acomp_free_streams(&deflate_streams);
  198. }
  199. module_init(deflate_mod_init);
  200. module_exit(deflate_mod_fini);
  201. MODULE_LICENSE("GPL");
  202. MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
  203. MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
  204. MODULE_AUTHOR("Ard Biesheuvel <ardb@kernel.org>");
  205. MODULE_AUTHOR("Herbert Xu <herbert@gondor.apana.org.au>");
  206. MODULE_ALIAS_CRYPTO("deflate");
  207. MODULE_ALIAS_CRYPTO("deflate-generic");