c_zstd.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. /*
  2. * Copyright 1998-2023 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. *
  9. * Uses zstd compression library from https://github.com/facebook/zstd
  10. * Requires version 1.4.x (latest as of this writing is 1.4.5)
  11. * Using custom free functions require static linking, so that is disabled when
  12. * using the shared library.
  13. */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <openssl/objects.h>
  18. #include "internal/comp.h"
  19. #include <openssl/err.h>
  20. #include "crypto/cryptlib.h"
  21. #include "internal/bio.h"
  22. #include "internal/thread_once.h"
  23. #include "comp_local.h"
  24. COMP_METHOD *COMP_zstd(void);
  25. #ifdef OPENSSL_NO_ZSTD
  26. # undef ZSTD_SHARED
  27. #else
  28. # ifndef ZSTD_SHARED
  29. # define ZSTD_STATIC_LINKING_ONLY
  30. # endif
  31. # include <zstd.h>
  32. /* Note: There is also a linux zstd.h file in the kernel source */
  33. # ifndef ZSTD_H_235446
  34. # error Wrong (i.e. linux) zstd.h included.
  35. # endif
  36. # if ZSTD_VERSION_MAJOR != 1 && ZSTD_VERSION_MINOR < 4
  37. # error Expecting version 1.4 or greater of ZSTD
  38. # endif
  39. # ifndef ZSTD_SHARED
  40. /* memory allocations functions for zstd initialisation */
  41. static void *zstd_alloc(void *opaque, size_t size)
  42. {
  43. return OPENSSL_zalloc(size);
  44. }
  45. static void zstd_free(void *opaque, void *address)
  46. {
  47. OPENSSL_free(address);
  48. }
  49. static ZSTD_customMem zstd_mem_funcs = {
  50. zstd_alloc,
  51. zstd_free,
  52. NULL
  53. };
  54. # endif
  55. /*
  56. * When OpenSSL is built on Windows, we do not want to require that
  57. * the LIBZSTD.DLL be available in order for the OpenSSL DLLs to
  58. * work. Therefore, all ZSTD routines are loaded at run time
  59. * and we do not link to a .LIB file when ZSTD_SHARED is set.
  60. */
  61. # if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
  62. # include <windows.h>
  63. # endif
  64. # ifdef ZSTD_SHARED
  65. # include "internal/dso.h"
  66. /* Function pointers */
  67. typedef ZSTD_CStream* (*createCStream_ft)(void);
  68. typedef size_t (*initCStream_ft)(ZSTD_CStream*, int);
  69. typedef size_t (*freeCStream_ft)(ZSTD_CStream*);
  70. typedef size_t (*compressStream2_ft)(ZSTD_CCtx*, ZSTD_outBuffer*, ZSTD_inBuffer*, ZSTD_EndDirective);
  71. typedef size_t (*flushStream_ft)(ZSTD_CStream*, ZSTD_outBuffer*);
  72. typedef size_t (*endStream_ft)(ZSTD_CStream*, ZSTD_outBuffer*);
  73. typedef size_t (*compress_ft)(void*, size_t, const void*, size_t, int);
  74. typedef ZSTD_DStream* (*createDStream_ft)(void);
  75. typedef size_t (*initDStream_ft)(ZSTD_DStream*);
  76. typedef size_t (*freeDStream_ft)(ZSTD_DStream*);
  77. typedef size_t (*decompressStream_ft)(ZSTD_DStream*, ZSTD_outBuffer*, ZSTD_inBuffer*);
  78. typedef size_t (*decompress_ft)(void*, size_t, const void*, size_t);
  79. typedef unsigned (*isError_ft)(size_t);
  80. typedef const char* (*getErrorName_ft)(size_t);
  81. typedef size_t (*DStreamInSize_ft)(void);
  82. typedef size_t (*CStreamInSize_ft)(void);
  83. static createCStream_ft p_createCStream = NULL;
  84. static initCStream_ft p_initCStream = NULL;
  85. static freeCStream_ft p_freeCStream = NULL;
  86. static compressStream2_ft p_compressStream2 = NULL;
  87. static flushStream_ft p_flushStream = NULL;
  88. static endStream_ft p_endStream = NULL;
  89. static compress_ft p_compress = NULL;
  90. static createDStream_ft p_createDStream = NULL;
  91. static initDStream_ft p_initDStream = NULL;
  92. static freeDStream_ft p_freeDStream = NULL;
  93. static decompressStream_ft p_decompressStream = NULL;
  94. static decompress_ft p_decompress = NULL;
  95. static isError_ft p_isError = NULL;
  96. static getErrorName_ft p_getErrorName = NULL;
  97. static DStreamInSize_ft p_DStreamInSize = NULL;
  98. static CStreamInSize_ft p_CStreamInSize = NULL;
  99. static DSO *zstd_dso = NULL;
  100. # define ZSTD_createCStream p_createCStream
  101. # define ZSTD_initCStream p_initCStream
  102. # define ZSTD_freeCStream p_freeCStream
  103. # define ZSTD_compressStream2 p_compressStream2
  104. # define ZSTD_flushStream p_flushStream
  105. # define ZSTD_endStream p_endStream
  106. # define ZSTD_compress p_compress
  107. # define ZSTD_createDStream p_createDStream
  108. # define ZSTD_initDStream p_initDStream
  109. # define ZSTD_freeDStream p_freeDStream
  110. # define ZSTD_decompressStream p_decompressStream
  111. # define ZSTD_decompress p_decompress
  112. # define ZSTD_isError p_isError
  113. # define ZSTD_getErrorName p_getErrorName
  114. # define ZSTD_DStreamInSize p_DStreamInSize
  115. # define ZSTD_CStreamInSize p_CStreamInSize
  116. # endif /* ifdef ZSTD_SHARED */
  117. struct zstd_state {
  118. ZSTD_CStream *compressor;
  119. ZSTD_DStream *decompressor;
  120. };
  121. static int zstd_stateful_init(COMP_CTX *ctx)
  122. {
  123. struct zstd_state *state = OPENSSL_zalloc(sizeof(*state));
  124. if (state == NULL)
  125. return 0;
  126. # ifdef ZSTD_SHARED
  127. state->compressor = ZSTD_createCStream();
  128. # else
  129. state->compressor = ZSTD_createCStream_advanced(zstd_mem_funcs);
  130. # endif
  131. if (state->compressor == NULL)
  132. goto err;
  133. ZSTD_initCStream(state->compressor, ZSTD_CLEVEL_DEFAULT);
  134. # ifdef ZSTD_SHARED
  135. state->decompressor = ZSTD_createDStream();
  136. # else
  137. state->decompressor = ZSTD_createDStream_advanced(zstd_mem_funcs);
  138. # endif
  139. if (state->decompressor == NULL)
  140. goto err;
  141. ZSTD_initDStream(state->decompressor);
  142. ctx->data = state;
  143. return 1;
  144. err:
  145. ZSTD_freeCStream(state->compressor);
  146. ZSTD_freeDStream(state->decompressor);
  147. OPENSSL_free(state);
  148. return 0;
  149. }
  150. static void zstd_stateful_finish(COMP_CTX *ctx)
  151. {
  152. struct zstd_state *state = ctx->data;
  153. if (state != NULL) {
  154. ZSTD_freeCStream(state->compressor);
  155. ZSTD_freeDStream(state->decompressor);
  156. OPENSSL_free(state);
  157. ctx->data = NULL;
  158. }
  159. }
  160. static ossl_ssize_t zstd_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
  161. size_t olen, unsigned char *in,
  162. size_t ilen)
  163. {
  164. ZSTD_inBuffer inbuf;
  165. ZSTD_outBuffer outbuf;
  166. size_t ret;
  167. ossl_ssize_t fret;
  168. struct zstd_state *state = ctx->data;
  169. inbuf.src = in;
  170. inbuf.size = ilen;
  171. inbuf.pos = 0;
  172. outbuf.dst = out;
  173. outbuf.size = olen;
  174. outbuf.pos = 0;
  175. if (state == NULL)
  176. return -1;
  177. /* If input length is zero, end the stream/frame ? */
  178. if (ilen == 0) {
  179. ret = ZSTD_endStream(state->compressor, &outbuf);
  180. if (ZSTD_isError(ret))
  181. return -1;
  182. goto end;
  183. }
  184. /*
  185. * The finish API does not provide a final output buffer,
  186. * so each compress operation has to be ended, if all
  187. * the input data can't be accepted, or there is more output,
  188. * this has to be considered an error, since there is no more
  189. * output buffer space.
  190. */
  191. do {
  192. ret = ZSTD_compressStream2(state->compressor, &outbuf, &inbuf, ZSTD_e_continue);
  193. if (ZSTD_isError(ret))
  194. return -1;
  195. /* do I need to check for ret == 0 ? */
  196. } while (inbuf.pos < inbuf.size);
  197. /* Did not consume all the data */
  198. if (inbuf.pos < inbuf.size)
  199. return -1;
  200. ret = ZSTD_flushStream(state->compressor, &outbuf);
  201. if (ZSTD_isError(ret))
  202. return -1;
  203. end:
  204. if (outbuf.pos > OSSL_SSIZE_MAX)
  205. return -1;
  206. fret = (ossl_ssize_t)outbuf.pos;
  207. if (fret < 0)
  208. return -1;
  209. return fret;
  210. }
  211. static ossl_ssize_t zstd_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
  212. size_t olen, unsigned char *in,
  213. size_t ilen)
  214. {
  215. ZSTD_inBuffer inbuf;
  216. ZSTD_outBuffer outbuf;
  217. size_t ret;
  218. ossl_ssize_t fret;
  219. struct zstd_state *state = ctx->data;
  220. inbuf.src = in;
  221. inbuf.size = ilen;
  222. inbuf.pos = 0;
  223. outbuf.dst = out;
  224. outbuf.size = olen;
  225. outbuf.pos = 0;
  226. if (state == NULL)
  227. return -1;
  228. if (ilen == 0)
  229. return 0;
  230. do {
  231. ret = ZSTD_decompressStream(state->decompressor, &outbuf, &inbuf);
  232. if (ZSTD_isError(ret))
  233. return -1;
  234. /* If we completed a frame, and there's more data, try again */
  235. } while (ret == 0 && inbuf.pos < inbuf.size);
  236. /* Did not consume all the data */
  237. if (inbuf.pos < inbuf.size)
  238. return -1;
  239. if (outbuf.pos > OSSL_SSIZE_MAX)
  240. return -1;
  241. fret = (ossl_ssize_t)outbuf.pos;
  242. if (fret < 0)
  243. return -1;
  244. return fret;
  245. }
  246. static COMP_METHOD zstd_stateful_method = {
  247. NID_zstd,
  248. LN_zstd,
  249. zstd_stateful_init,
  250. zstd_stateful_finish,
  251. zstd_stateful_compress_block,
  252. zstd_stateful_expand_block
  253. };
  254. static int zstd_oneshot_init(COMP_CTX *ctx)
  255. {
  256. return 1;
  257. }
  258. static void zstd_oneshot_finish(COMP_CTX *ctx)
  259. {
  260. }
  261. static ossl_ssize_t zstd_oneshot_compress_block(COMP_CTX *ctx, unsigned char *out,
  262. size_t olen, unsigned char *in,
  263. size_t ilen)
  264. {
  265. size_t out_size;
  266. ossl_ssize_t ret;
  267. if (ilen == 0)
  268. return 0;
  269. /* Note: uses STDLIB memory allocators */
  270. out_size = ZSTD_compress(out, olen, in, ilen, ZSTD_CLEVEL_DEFAULT);
  271. if (ZSTD_isError(out_size))
  272. return -1;
  273. if (out_size > OSSL_SSIZE_MAX)
  274. return -1;
  275. ret = (ossl_ssize_t)out_size;
  276. if (ret < 0)
  277. return -1;
  278. return ret;
  279. }
  280. static ossl_ssize_t zstd_oneshot_expand_block(COMP_CTX *ctx, unsigned char *out,
  281. size_t olen, unsigned char *in,
  282. size_t ilen)
  283. {
  284. size_t out_size;
  285. ossl_ssize_t ret;
  286. if (ilen == 0)
  287. return 0;
  288. /* Note: uses STDLIB memory allocators */
  289. out_size = ZSTD_decompress(out, olen, in, ilen);
  290. if (ZSTD_isError(out_size))
  291. return -1;
  292. if (out_size > OSSL_SSIZE_MAX)
  293. return -1;
  294. ret = (ossl_ssize_t)out_size;
  295. if (ret < 0)
  296. return -1;
  297. return ret;
  298. }
  299. static COMP_METHOD zstd_oneshot_method = {
  300. NID_zstd,
  301. LN_zstd,
  302. zstd_oneshot_init,
  303. zstd_oneshot_finish,
  304. zstd_oneshot_compress_block,
  305. zstd_oneshot_expand_block
  306. };
  307. static CRYPTO_ONCE zstd_once = CRYPTO_ONCE_STATIC_INIT;
  308. DEFINE_RUN_ONCE_STATIC(ossl_comp_zstd_init)
  309. {
  310. # ifdef ZSTD_SHARED
  311. # if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
  312. # define LIBZSTD "LIBZSTD"
  313. # else
  314. # define LIBZSTD "zstd"
  315. # endif
  316. zstd_dso = DSO_load(NULL, LIBZSTD, NULL, 0);
  317. if (zstd_dso != NULL) {
  318. p_createCStream = (createCStream_ft)DSO_bind_func(zstd_dso, "ZSTD_createCStream");
  319. p_initCStream = (initCStream_ft)DSO_bind_func(zstd_dso, "ZSTD_initCStream");
  320. p_freeCStream = (freeCStream_ft)DSO_bind_func(zstd_dso, "ZSTD_freeCStream");
  321. p_compressStream2 = (compressStream2_ft)DSO_bind_func(zstd_dso, "ZSTD_compressStream2");
  322. p_flushStream = (flushStream_ft)DSO_bind_func(zstd_dso, "ZSTD_flushStream");
  323. p_endStream = (endStream_ft)DSO_bind_func(zstd_dso, "ZSTD_endStream");
  324. p_compress = (compress_ft)DSO_bind_func(zstd_dso, "ZSTD_compress");
  325. p_createDStream = (createDStream_ft)DSO_bind_func(zstd_dso, "ZSTD_createDStream");
  326. p_initDStream = (initDStream_ft)DSO_bind_func(zstd_dso, "ZSTD_initDStream");
  327. p_freeDStream = (freeDStream_ft)DSO_bind_func(zstd_dso, "ZSTD_freeDStream");
  328. p_decompressStream = (decompressStream_ft)DSO_bind_func(zstd_dso, "ZSTD_decompressStream");
  329. p_decompress = (decompress_ft)DSO_bind_func(zstd_dso, "ZSTD_decompress");
  330. p_isError = (isError_ft)DSO_bind_func(zstd_dso, "ZSTD_isError");
  331. p_getErrorName = (getErrorName_ft)DSO_bind_func(zstd_dso, "ZSTD_getErrorName");
  332. p_DStreamInSize = (DStreamInSize_ft)DSO_bind_func(zstd_dso, "ZSTD_DStreamInSize");
  333. p_CStreamInSize = (CStreamInSize_ft)DSO_bind_func(zstd_dso, "ZSTD_CStreamInSize");
  334. }
  335. if (p_createCStream == NULL || p_initCStream == NULL || p_freeCStream == NULL
  336. || p_compressStream2 == NULL || p_flushStream == NULL || p_endStream == NULL
  337. || p_compress == NULL || p_createDStream == NULL || p_initDStream == NULL
  338. || p_freeDStream == NULL || p_decompressStream == NULL || p_decompress == NULL
  339. || p_isError == NULL || p_getErrorName == NULL || p_DStreamInSize == NULL
  340. || p_CStreamInSize == NULL) {
  341. ossl_comp_zstd_cleanup();
  342. return 0;
  343. }
  344. # endif
  345. return 1;
  346. }
  347. #endif /* ifndef ZSTD / else */
  348. COMP_METHOD *COMP_zstd(void)
  349. {
  350. COMP_METHOD *meth = NULL;
  351. #ifndef OPENSSL_NO_ZSTD
  352. if (RUN_ONCE(&zstd_once, ossl_comp_zstd_init))
  353. meth = &zstd_stateful_method;
  354. #endif
  355. return meth;
  356. }
  357. COMP_METHOD *COMP_zstd_oneshot(void)
  358. {
  359. COMP_METHOD *meth = NULL;
  360. #ifndef OPENSSL_NO_ZSTD
  361. if (RUN_ONCE(&zstd_once, ossl_comp_zstd_init))
  362. meth = &zstd_oneshot_method;
  363. #endif
  364. return meth;
  365. }
  366. /* Also called from OPENSSL_cleanup() */
  367. void ossl_comp_zstd_cleanup(void)
  368. {
  369. #ifdef ZSTD_SHARED
  370. DSO_free(zstd_dso);
  371. zstd_dso = NULL;
  372. p_createCStream = NULL;
  373. p_initCStream = NULL;
  374. p_freeCStream = NULL;
  375. p_compressStream2 = NULL;
  376. p_flushStream = NULL;
  377. p_endStream = NULL;
  378. p_compress = NULL;
  379. p_createDStream = NULL;
  380. p_initDStream = NULL;
  381. p_freeDStream = NULL;
  382. p_decompressStream = NULL;
  383. p_decompress = NULL;
  384. p_isError = NULL;
  385. p_getErrorName = NULL;
  386. p_DStreamInSize = NULL;
  387. p_CStreamInSize = NULL;
  388. #endif
  389. }
  390. #ifndef OPENSSL_NO_ZSTD
  391. /* Zstd-based compression/decompression filter BIO */
  392. typedef struct {
  393. struct { /* input structure */
  394. ZSTD_DStream *state;
  395. ZSTD_inBuffer inbuf; /* has const src */
  396. size_t bufsize;
  397. void* buffer;
  398. } decompress;
  399. struct { /* output structure */
  400. ZSTD_CStream *state;
  401. ZSTD_outBuffer outbuf;
  402. size_t bufsize;
  403. size_t write_pos;
  404. } compress;
  405. } BIO_ZSTD_CTX;
  406. # define ZSTD_DEFAULT_BUFSIZE 1024
  407. static int bio_zstd_new(BIO *bi);
  408. static int bio_zstd_free(BIO *bi);
  409. static int bio_zstd_read(BIO *b, char *out, int outl);
  410. static int bio_zstd_write(BIO *b, const char *in, int inl);
  411. static long bio_zstd_ctrl(BIO *b, int cmd, long num, void *ptr);
  412. static long bio_zstd_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
  413. static const BIO_METHOD bio_meth_zstd = {
  414. BIO_TYPE_COMP,
  415. "zstd",
  416. /* TODO: Convert to new style write function */
  417. bwrite_conv,
  418. bio_zstd_write,
  419. /* TODO: Convert to new style read function */
  420. bread_conv,
  421. bio_zstd_read,
  422. NULL, /* bio_zstd_puts, */
  423. NULL, /* bio_zstd_gets, */
  424. bio_zstd_ctrl,
  425. bio_zstd_new,
  426. bio_zstd_free,
  427. bio_zstd_callback_ctrl
  428. };
  429. #endif
  430. const BIO_METHOD *BIO_f_zstd(void)
  431. {
  432. #ifndef OPENSSL_NO_ZSTD
  433. if (RUN_ONCE(&zstd_once, ossl_comp_zstd_init))
  434. return &bio_meth_zstd;
  435. #endif
  436. return NULL;
  437. }
  438. #ifndef OPENSSL_NO_ZSTD
  439. static int bio_zstd_new(BIO *bi)
  440. {
  441. BIO_ZSTD_CTX *ctx;
  442. # ifdef ZSTD_SHARED
  443. (void)COMP_zstd();
  444. if (zstd_dso == NULL) {
  445. ERR_raise(ERR_LIB_COMP, COMP_R_ZSTD_NOT_SUPPORTED);
  446. return 0;
  447. }
  448. # endif
  449. ctx = OPENSSL_zalloc(sizeof(*ctx));
  450. if (ctx == NULL) {
  451. ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE);
  452. return 0;
  453. }
  454. # ifdef ZSTD_SHARED
  455. ctx->decompress.state = ZSTD_createDStream();
  456. # else
  457. ctx->decompress.state = ZSTD_createDStream_advanced(zstd_mem_funcs);
  458. # endif
  459. if (ctx->decompress.state == NULL)
  460. goto err;
  461. ZSTD_initDStream(ctx->decompress.state);
  462. ctx->decompress.bufsize = ZSTD_DStreamInSize();
  463. # ifdef ZSTD_SHARED
  464. ctx->compress.state = ZSTD_createCStream();
  465. # else
  466. ctx->compress.state = ZSTD_createCStream_advanced(zstd_mem_funcs);
  467. # endif
  468. if (ctx->compress.state == NULL)
  469. goto err;
  470. ZSTD_initCStream(ctx->compress.state, ZSTD_CLEVEL_DEFAULT);
  471. ctx->compress.bufsize = ZSTD_CStreamInSize();
  472. BIO_set_init(bi, 1);
  473. BIO_set_data(bi, ctx);
  474. return 1;
  475. err:
  476. ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE);
  477. ZSTD_freeDStream(ctx->decompress.state);
  478. ZSTD_freeCStream(ctx->compress.state);
  479. OPENSSL_free(ctx);
  480. return 0;
  481. }
  482. static int bio_zstd_free(BIO *bi)
  483. {
  484. BIO_ZSTD_CTX *ctx;
  485. if (bi == NULL)
  486. return 0;
  487. ctx = BIO_get_data(bi);
  488. if (ctx != NULL) {
  489. ZSTD_freeDStream(ctx->decompress.state);
  490. OPENSSL_free(ctx->decompress.buffer);
  491. ZSTD_freeCStream(ctx->compress.state);
  492. OPENSSL_free(ctx->compress.outbuf.dst);
  493. OPENSSL_free(ctx);
  494. }
  495. BIO_set_data(bi, NULL);
  496. BIO_set_init(bi, 0);
  497. return 1;
  498. }
  499. static int bio_zstd_read(BIO *b, char *out, int outl)
  500. {
  501. BIO_ZSTD_CTX *ctx;
  502. size_t zret;
  503. int ret;
  504. ZSTD_outBuffer outBuf;
  505. BIO *next = BIO_next(b);
  506. if (out == NULL || outl <= 0)
  507. return 0;
  508. ctx = BIO_get_data(b);
  509. BIO_clear_retry_flags(b);
  510. if (ctx->decompress.buffer == NULL) {
  511. ctx->decompress.buffer = OPENSSL_malloc(ctx->decompress.bufsize);
  512. if (ctx->decompress.buffer == NULL) {
  513. ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE);
  514. return 0;
  515. }
  516. ctx->decompress.inbuf.src = ctx->decompress.buffer;
  517. ctx->decompress.inbuf.size = 0;
  518. ctx->decompress.inbuf.pos = 0;
  519. }
  520. /* Copy output data directly to supplied buffer */
  521. outBuf.dst = out;
  522. outBuf.size = (size_t)outl;
  523. outBuf.pos = 0;
  524. for (;;) {
  525. /* Decompress while data available */
  526. do {
  527. zret = ZSTD_decompressStream(ctx->decompress.state, &outBuf, &ctx->decompress.inbuf);
  528. if (ZSTD_isError(zret)) {
  529. ERR_raise(ERR_LIB_COMP, COMP_R_ZSTD_DECOMPRESS_ERROR);
  530. ERR_add_error_data(1, ZSTD_getErrorName(zret));
  531. return -1;
  532. }
  533. /* No more output space */
  534. if (outBuf.pos == outBuf.size)
  535. return outBuf.pos;
  536. } while (ctx->decompress.inbuf.pos < ctx->decompress.inbuf.size);
  537. /*
  538. * No data in input buffer try to read some in, if an error then
  539. * return the total data read.
  540. */
  541. ret = BIO_read(next, ctx->decompress.buffer, ctx->decompress.bufsize);
  542. if (ret <= 0) {
  543. BIO_copy_next_retry(b);
  544. if (ret < 0 && outBuf.pos == 0)
  545. return ret;
  546. return outBuf.pos;
  547. }
  548. ctx->decompress.inbuf.size = ret;
  549. ctx->decompress.inbuf.pos = 0;
  550. }
  551. }
  552. static int bio_zstd_write(BIO *b, const char *in, int inl)
  553. {
  554. BIO_ZSTD_CTX *ctx;
  555. size_t zret;
  556. ZSTD_inBuffer inBuf;
  557. int ret;
  558. int done = 0;
  559. BIO *next = BIO_next(b);
  560. if (in == NULL || inl <= 0)
  561. return 0;
  562. ctx = BIO_get_data(b);
  563. BIO_clear_retry_flags(b);
  564. if (ctx->compress.outbuf.dst == NULL) {
  565. ctx->compress.outbuf.dst = OPENSSL_malloc(ctx->compress.bufsize);
  566. if (ctx->compress.outbuf.dst == NULL) {
  567. ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE);
  568. return 0;
  569. }
  570. ctx->compress.outbuf.size = ctx->compress.bufsize;
  571. ctx->compress.outbuf.pos = 0;
  572. ctx->compress.write_pos = 0;
  573. }
  574. /* Obtain input data directly from supplied buffer */
  575. inBuf.src = in;
  576. inBuf.size = inl;
  577. inBuf.pos = 0;
  578. for (;;) {
  579. /* If data in output buffer write it first */
  580. while (ctx->compress.write_pos < ctx->compress.outbuf.pos) {
  581. ret = BIO_write(next, (unsigned char*)ctx->compress.outbuf.dst + ctx->compress.write_pos,
  582. ctx->compress.outbuf.pos - ctx->compress.write_pos);
  583. if (ret <= 0) {
  584. BIO_copy_next_retry(b);
  585. if (ret < 0 && inBuf.pos == 0)
  586. return ret;
  587. return inBuf.pos;
  588. }
  589. ctx->compress.write_pos += ret;
  590. }
  591. /* Have we consumed all supplied data? */
  592. if (done)
  593. return inBuf.pos;
  594. /* Reset buffer */
  595. ctx->compress.outbuf.pos = 0;
  596. ctx->compress.outbuf.size = ctx->compress.bufsize;
  597. ctx->compress.write_pos = 0;
  598. /* Compress some more */
  599. zret = ZSTD_compressStream2(ctx->compress.state, &ctx->compress.outbuf, &inBuf, ZSTD_e_end);
  600. if (ZSTD_isError(zret)) {
  601. ERR_raise(ERR_LIB_COMP, COMP_R_ZSTD_COMPRESS_ERROR);
  602. ERR_add_error_data(1, ZSTD_getErrorName(zret));
  603. return 0;
  604. } else if (zret == 0) {
  605. done = 1;
  606. }
  607. }
  608. }
  609. static int bio_zstd_flush(BIO *b)
  610. {
  611. BIO_ZSTD_CTX *ctx;
  612. size_t zret;
  613. int ret;
  614. BIO *next = BIO_next(b);
  615. ctx = BIO_get_data(b);
  616. /* If no data written or already flush show success */
  617. if (ctx->compress.outbuf.dst == NULL)
  618. return 1;
  619. BIO_clear_retry_flags(b);
  620. /* No more input data */
  621. ctx->compress.outbuf.pos = 0;
  622. ctx->compress.outbuf.size = ctx->compress.bufsize;
  623. ctx->compress.write_pos = 0;
  624. for (;;) {
  625. /* If data in output buffer write it first */
  626. while (ctx->compress.write_pos < ctx->compress.outbuf.pos) {
  627. ret = BIO_write(next, (unsigned char*)ctx->compress.outbuf.dst + ctx->compress.write_pos,
  628. ctx->compress.outbuf.pos - ctx->compress.write_pos);
  629. if (ret <= 0) {
  630. BIO_copy_next_retry(b);
  631. return ret;
  632. }
  633. ctx->compress.write_pos += ret;
  634. }
  635. /* Reset buffer */
  636. ctx->compress.outbuf.pos = 0;
  637. ctx->compress.outbuf.size = ctx->compress.bufsize;
  638. ctx->compress.write_pos = 0;
  639. /* Compress some more */
  640. zret = ZSTD_flushStream(ctx->compress.state, &ctx->compress.outbuf);
  641. if (ZSTD_isError(zret)) {
  642. ERR_raise(ERR_LIB_COMP, COMP_R_ZSTD_DECODE_ERROR);
  643. ERR_add_error_data(1, ZSTD_getErrorName(zret));
  644. return 0;
  645. }
  646. if (zret == 0)
  647. return 1;
  648. }
  649. }
  650. static long bio_zstd_ctrl(BIO *b, int cmd, long num, void *ptr)
  651. {
  652. BIO_ZSTD_CTX *ctx;
  653. int ret = 0, *ip;
  654. size_t ibs, obs;
  655. unsigned char *tmp;
  656. BIO *next = BIO_next(b);
  657. if (next == NULL)
  658. return 0;
  659. ctx = BIO_get_data(b);
  660. switch (cmd) {
  661. case BIO_CTRL_RESET:
  662. ctx->compress.write_pos = 0;
  663. ctx->compress.bufsize = 0;
  664. ret = 1;
  665. break;
  666. case BIO_CTRL_FLUSH:
  667. ret = bio_zstd_flush(b);
  668. if (ret > 0) {
  669. ret = BIO_flush(next);
  670. BIO_copy_next_retry(b);
  671. }
  672. break;
  673. case BIO_C_SET_BUFF_SIZE:
  674. ibs = ctx->decompress.bufsize;
  675. obs = ctx->compress.bufsize;
  676. if (ptr != NULL) {
  677. ip = ptr;
  678. if (*ip == 0)
  679. ibs = (size_t)num;
  680. else
  681. obs = (size_t)num;
  682. } else {
  683. obs = ibs = (size_t)num;
  684. }
  685. if (ibs > 0 && ibs != ctx->decompress.bufsize) {
  686. if (ctx->decompress.buffer != NULL) {
  687. tmp = OPENSSL_realloc(ctx->decompress.buffer, ibs);
  688. if (tmp == NULL)
  689. return 0;
  690. if (ctx->decompress.inbuf.src == ctx->decompress.buffer)
  691. ctx->decompress.inbuf.src = tmp;
  692. ctx->decompress.buffer = tmp;
  693. }
  694. ctx->decompress.bufsize = ibs;
  695. }
  696. if (obs > 0 && obs != ctx->compress.bufsize) {
  697. if (ctx->compress.outbuf.dst != NULL) {
  698. tmp = OPENSSL_realloc(ctx->compress.outbuf.dst, obs);
  699. if (tmp == NULL)
  700. return 0;
  701. ctx->compress.outbuf.dst = tmp;
  702. }
  703. ctx->compress.bufsize = obs;
  704. }
  705. ret = 1;
  706. break;
  707. case BIO_C_DO_STATE_MACHINE:
  708. BIO_clear_retry_flags(b);
  709. ret = BIO_ctrl(next, cmd, num, ptr);
  710. BIO_copy_next_retry(b);
  711. break;
  712. case BIO_CTRL_WPENDING:
  713. if (ctx->compress.outbuf.pos < ctx->compress.outbuf.size)
  714. ret = 1;
  715. else
  716. ret = BIO_ctrl(next, cmd, num, ptr);
  717. break;
  718. case BIO_CTRL_PENDING:
  719. if (ctx->decompress.inbuf.pos < ctx->decompress.inbuf.size)
  720. ret = 1;
  721. else
  722. ret = BIO_ctrl(next, cmd, num, ptr);
  723. break;
  724. default:
  725. ret = BIO_ctrl(next, cmd, num, ptr);
  726. break;
  727. }
  728. return ret;
  729. }
  730. static long bio_zstd_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
  731. {
  732. BIO *next = BIO_next(b);
  733. if (next == NULL)
  734. return 0;
  735. return BIO_callback_ctrl(next, cmd, fp);
  736. }
  737. #endif