c_brotli.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  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 brotli compression library from https://github.com/google/brotli
  10. */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <openssl/objects.h>
  15. #include "internal/comp.h"
  16. #include <openssl/err.h>
  17. #include "crypto/cryptlib.h"
  18. #include "internal/bio.h"
  19. #include "internal/thread_once.h"
  20. #include "comp_local.h"
  21. COMP_METHOD *COMP_brotli(void);
  22. #ifdef OPENSSL_NO_BROTLI
  23. # undef BROTLI_SHARED
  24. #else
  25. # include <brotli/decode.h>
  26. # include <brotli/encode.h>
  27. /* memory allocations functions for brotli initialisation */
  28. static void *brotli_alloc(void *opaque, size_t size)
  29. {
  30. return OPENSSL_zalloc(size);
  31. }
  32. static void brotli_free(void *opaque, void *address)
  33. {
  34. OPENSSL_free(address);
  35. }
  36. /*
  37. * When OpenSSL is built on Windows, we do not want to require that
  38. * the BROTLI.DLL be available in order for the OpenSSL DLLs to
  39. * work. Therefore, all BROTLI routines are loaded at run time
  40. * and we do not link to a .LIB file when BROTLI_SHARED is set.
  41. */
  42. # if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
  43. # include <windows.h>
  44. # endif
  45. # ifdef BROTLI_SHARED
  46. # include "internal/dso.h"
  47. /* Function pointers */
  48. typedef BrotliEncoderState *(*encode_init_ft)(brotli_alloc_func, brotli_free_func, void *);
  49. typedef BROTLI_BOOL (*encode_stream_ft)(BrotliEncoderState *, BrotliEncoderOperation, size_t *, const uint8_t **, size_t *, uint8_t **, size_t *);
  50. typedef BROTLI_BOOL (*encode_has_more_ft)(BrotliEncoderState *);
  51. typedef void (*encode_end_ft)(BrotliEncoderState *);
  52. typedef BROTLI_BOOL (*encode_oneshot_ft)(int, int, BrotliEncoderMode, size_t, const uint8_t in[], size_t *, uint8_t out[]);
  53. typedef BrotliDecoderState *(*decode_init_ft)(brotli_alloc_func, brotli_free_func, void *);
  54. typedef BROTLI_BOOL (*decode_stream_ft)(BrotliDecoderState *, size_t *, const uint8_t **, size_t *, uint8_t **, size_t *);
  55. typedef BROTLI_BOOL (*decode_has_more_ft)(BrotliDecoderState *);
  56. typedef void (*decode_end_ft)(BrotliDecoderState *);
  57. typedef BrotliDecoderErrorCode (*decode_error_ft)(BrotliDecoderState *);
  58. typedef const char *(*decode_error_string_ft)(BrotliDecoderErrorCode);
  59. typedef BROTLI_BOOL (*decode_is_finished_ft)(BrotliDecoderState *);
  60. typedef BrotliDecoderResult (*decode_oneshot_ft)(size_t, const uint8_t in[], size_t *, uint8_t out[]);
  61. static encode_init_ft p_encode_init = NULL;
  62. static encode_stream_ft p_encode_stream = NULL;
  63. static encode_has_more_ft p_encode_has_more = NULL;
  64. static encode_end_ft p_encode_end = NULL;
  65. static encode_oneshot_ft p_encode_oneshot = NULL;
  66. static decode_init_ft p_decode_init = NULL;
  67. static decode_stream_ft p_decode_stream = NULL;
  68. static decode_has_more_ft p_decode_has_more = NULL;
  69. static decode_end_ft p_decode_end = NULL;
  70. static decode_error_ft p_decode_error = NULL;
  71. static decode_error_string_ft p_decode_error_string = NULL;
  72. static decode_is_finished_ft p_decode_is_finished = NULL;
  73. static decode_oneshot_ft p_decode_oneshot = NULL;
  74. static DSO *brotli_encode_dso = NULL;
  75. static DSO *brotli_decode_dso = NULL;
  76. # define BrotliEncoderCreateInstance p_encode_init
  77. # define BrotliEncoderCompressStream p_encode_stream
  78. # define BrotliEncoderHasMoreOutput p_encode_has_more
  79. # define BrotliEncoderDestroyInstance p_encode_end
  80. # define BrotliEncoderCompress p_encode_oneshot
  81. # define BrotliDecoderCreateInstance p_decode_init
  82. # define BrotliDecoderDecompressStream p_decode_stream
  83. # define BrotliDecoderHasMoreOutput p_decode_has_more
  84. # define BrotliDecoderDestroyInstance p_decode_end
  85. # define BrotliDecoderGetErrorCode p_decode_error
  86. # define BrotliDecoderErrorString p_decode_error_string
  87. # define BrotliDecoderIsFinished p_decode_is_finished
  88. # define BrotliDecoderDecompress p_decode_oneshot
  89. # endif /* ifdef BROTLI_SHARED */
  90. struct brotli_state {
  91. BrotliEncoderState *encoder;
  92. BrotliDecoderState *decoder;
  93. };
  94. static int brotli_stateful_init(COMP_CTX *ctx)
  95. {
  96. struct brotli_state *state = OPENSSL_zalloc(sizeof(*state));
  97. if (state == NULL)
  98. return 0;
  99. state->encoder = BrotliEncoderCreateInstance(brotli_alloc, brotli_free, NULL);
  100. if (state->encoder == NULL)
  101. goto err;
  102. state->decoder = BrotliDecoderCreateInstance(brotli_alloc, brotli_free, NULL);
  103. if (state->decoder == NULL)
  104. goto err;
  105. ctx->data = state;
  106. return 1;
  107. err:
  108. BrotliDecoderDestroyInstance(state->decoder);
  109. BrotliEncoderDestroyInstance(state->encoder);
  110. OPENSSL_free(state);
  111. return 0;
  112. }
  113. static void brotli_stateful_finish(COMP_CTX *ctx)
  114. {
  115. struct brotli_state *state = ctx->data;
  116. if (state != NULL) {
  117. BrotliDecoderDestroyInstance(state->decoder);
  118. BrotliEncoderDestroyInstance(state->encoder);
  119. OPENSSL_free(state);
  120. ctx->data = NULL;
  121. }
  122. }
  123. static ossl_ssize_t brotli_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
  124. size_t olen, unsigned char *in,
  125. size_t ilen)
  126. {
  127. BROTLI_BOOL done;
  128. struct brotli_state *state = ctx->data;
  129. size_t in_avail = ilen;
  130. size_t out_avail = olen;
  131. if (state == NULL || olen > OSSL_SSIZE_MAX)
  132. return -1;
  133. if (ilen == 0)
  134. return 0;
  135. /*
  136. * The finish API does not provide a final output buffer,
  137. * so each compress operation has to be flushed, if all
  138. * the input data can't be accepted, or there is more output,
  139. * this has to be considered an error, since there is no more
  140. * output buffer space
  141. */
  142. done = BrotliEncoderCompressStream(state->encoder, BROTLI_OPERATION_FLUSH,
  143. &in_avail, (const uint8_t**)&in,
  144. &out_avail, &out, NULL);
  145. if (done == BROTLI_FALSE
  146. || in_avail != 0
  147. || BrotliEncoderHasMoreOutput(state->encoder))
  148. return -1;
  149. if (out_avail > olen)
  150. return -1;
  151. return (ossl_ssize_t)(olen - out_avail);
  152. }
  153. static ossl_ssize_t brotli_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
  154. size_t olen, unsigned char *in,
  155. size_t ilen)
  156. {
  157. BrotliDecoderResult result;
  158. struct brotli_state *state = ctx->data;
  159. size_t in_avail = ilen;
  160. size_t out_avail = olen;
  161. if (state == NULL || olen > OSSL_SSIZE_MAX)
  162. return -1;
  163. if (ilen == 0)
  164. return 0;
  165. result = BrotliDecoderDecompressStream(state->decoder, &in_avail,
  166. (const uint8_t**)&in, &out_avail,
  167. &out, NULL);
  168. if (result == BROTLI_DECODER_RESULT_ERROR
  169. || in_avail != 0
  170. || BrotliDecoderHasMoreOutput(state->decoder))
  171. return -1;
  172. if (out_avail > olen)
  173. return -1;
  174. return (ossl_ssize_t)(olen - out_avail);
  175. }
  176. static COMP_METHOD brotli_stateful_method = {
  177. NID_brotli,
  178. LN_brotli,
  179. brotli_stateful_init,
  180. brotli_stateful_finish,
  181. brotli_stateful_compress_block,
  182. brotli_stateful_expand_block
  183. };
  184. static int brotli_oneshot_init(COMP_CTX *ctx)
  185. {
  186. return 1;
  187. }
  188. static void brotli_oneshot_finish(COMP_CTX *ctx)
  189. {
  190. }
  191. static ossl_ssize_t brotli_oneshot_compress_block(COMP_CTX *ctx, unsigned char *out,
  192. size_t olen, unsigned char *in,
  193. size_t ilen)
  194. {
  195. size_t out_size = olen;
  196. ossl_ssize_t ret;
  197. if (ilen == 0)
  198. return 0;
  199. if (BrotliEncoderCompress(BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW,
  200. BROTLI_DEFAULT_MODE, ilen, in,
  201. &out_size, out) == BROTLI_FALSE)
  202. return -1;
  203. if (out_size > OSSL_SSIZE_MAX)
  204. return -1;
  205. ret = (ossl_ssize_t)out_size;
  206. if (ret < 0)
  207. return -1;
  208. return ret;
  209. }
  210. static ossl_ssize_t brotli_oneshot_expand_block(COMP_CTX *ctx, unsigned char *out,
  211. size_t olen, unsigned char *in,
  212. size_t ilen)
  213. {
  214. size_t out_size = olen;
  215. ossl_ssize_t ret;
  216. if (ilen == 0)
  217. return 0;
  218. if (BrotliDecoderDecompress(ilen, in, &out_size, out) != BROTLI_DECODER_RESULT_SUCCESS)
  219. return -1;
  220. if (out_size > OSSL_SSIZE_MAX)
  221. return -1;
  222. ret = (ossl_ssize_t)out_size;
  223. if (ret < 0)
  224. return -1;
  225. return ret;
  226. }
  227. static COMP_METHOD brotli_oneshot_method = {
  228. NID_brotli,
  229. LN_brotli,
  230. brotli_oneshot_init,
  231. brotli_oneshot_finish,
  232. brotli_oneshot_compress_block,
  233. brotli_oneshot_expand_block
  234. };
  235. static CRYPTO_ONCE brotli_once = CRYPTO_ONCE_STATIC_INIT;
  236. DEFINE_RUN_ONCE_STATIC(ossl_comp_brotli_init)
  237. {
  238. # ifdef BROTLI_SHARED
  239. # if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
  240. # define LIBBROTLIENC "BROTLIENC"
  241. # define LIBBROTLIDEC "BROTLIDEC"
  242. # else
  243. # define LIBBROTLIENC "brotlienc"
  244. # define LIBBROTLIDEC "brotlidec"
  245. # endif
  246. brotli_encode_dso = DSO_load(NULL, LIBBROTLIENC, NULL, 0);
  247. if (brotli_encode_dso != NULL) {
  248. p_encode_init = (encode_init_ft)DSO_bind_func(brotli_encode_dso, "BrotliEncoderCreateInstance");
  249. p_encode_stream = (encode_stream_ft)DSO_bind_func(brotli_encode_dso, "BrotliEncoderCompressStream");
  250. p_encode_has_more = (encode_has_more_ft)DSO_bind_func(brotli_encode_dso, "BrotliEncoderHasMoreOutput");
  251. p_encode_end = (encode_end_ft)DSO_bind_func(brotli_encode_dso, "BrotliEncoderDestroyInstance");
  252. p_encode_oneshot = (encode_oneshot_ft)DSO_bind_func(brotli_encode_dso, "BrotliEncoderCompress");
  253. }
  254. brotli_decode_dso = DSO_load(NULL, LIBBROTLIDEC, NULL, 0);
  255. if (brotli_decode_dso != NULL) {
  256. p_decode_init = (decode_init_ft)DSO_bind_func(brotli_decode_dso, "BrotliDecoderCreateInstance");
  257. p_decode_stream = (decode_stream_ft)DSO_bind_func(brotli_decode_dso, "BrotliDecoderDecompressStream");
  258. p_decode_has_more = (decode_has_more_ft)DSO_bind_func(brotli_decode_dso, "BrotliDecoderHasMoreOutput");
  259. p_decode_end = (decode_end_ft)DSO_bind_func(brotli_decode_dso, "BrotliDecoderDestroyInstance");
  260. p_decode_error = (decode_error_ft)DSO_bind_func(brotli_decode_dso, "BrotliDecoderGetErrorCode");
  261. p_decode_error_string = (decode_error_string_ft)DSO_bind_func(brotli_decode_dso, "BrotliDecoderErrorString");
  262. p_decode_is_finished = (decode_is_finished_ft)DSO_bind_func(brotli_decode_dso, "BrotliDecoderIsFinished");
  263. p_decode_oneshot = (decode_oneshot_ft)DSO_bind_func(brotli_decode_dso, "BrotliDecoderDecompress");
  264. }
  265. if (p_encode_init == NULL || p_encode_stream == NULL || p_encode_has_more == NULL
  266. || p_encode_end == NULL || p_encode_oneshot == NULL || p_decode_init == NULL
  267. || p_decode_stream == NULL || p_decode_has_more == NULL || p_decode_end == NULL
  268. || p_decode_error == NULL || p_decode_error_string == NULL || p_decode_is_finished == NULL
  269. || p_decode_oneshot == NULL) {
  270. ossl_comp_brotli_cleanup();
  271. return 0;
  272. }
  273. # endif
  274. return 1;
  275. }
  276. #endif /* ifndef BROTLI / else */
  277. COMP_METHOD *COMP_brotli(void)
  278. {
  279. COMP_METHOD *meth = NULL;
  280. #ifndef OPENSSL_NO_BROTLI
  281. if (RUN_ONCE(&brotli_once, ossl_comp_brotli_init))
  282. meth = &brotli_stateful_method;
  283. #endif
  284. return meth;
  285. }
  286. COMP_METHOD *COMP_brotli_oneshot(void)
  287. {
  288. COMP_METHOD *meth = NULL;
  289. #ifndef OPENSSL_NO_BROTLI
  290. if (RUN_ONCE(&brotli_once, ossl_comp_brotli_init))
  291. meth = &brotli_oneshot_method;
  292. #endif
  293. return meth;
  294. }
  295. /* Also called from OPENSSL_cleanup() */
  296. void ossl_comp_brotli_cleanup(void)
  297. {
  298. #ifdef BROTLI_SHARED
  299. DSO_free(brotli_encode_dso);
  300. brotli_encode_dso = NULL;
  301. DSO_free(brotli_decode_dso);
  302. brotli_decode_dso = NULL;
  303. p_encode_init = NULL;
  304. p_encode_stream = NULL;
  305. p_encode_has_more = NULL;
  306. p_encode_end = NULL;
  307. p_encode_oneshot = NULL;
  308. p_decode_init = NULL;
  309. p_decode_stream = NULL;
  310. p_decode_has_more = NULL;
  311. p_decode_end = NULL;
  312. p_decode_error = NULL;
  313. p_decode_error_string = NULL;
  314. p_decode_is_finished = NULL;
  315. p_decode_oneshot = NULL;
  316. #endif
  317. }
  318. #ifndef OPENSSL_NO_BROTLI
  319. /* Brotli-based compression/decompression filter BIO */
  320. typedef struct {
  321. struct { /* input structure */
  322. size_t avail_in;
  323. unsigned char *next_in;
  324. size_t avail_out;
  325. unsigned char *next_out;
  326. unsigned char *buf;
  327. size_t bufsize;
  328. BrotliDecoderState *state;
  329. } decode;
  330. struct { /* output structure */
  331. size_t avail_in;
  332. unsigned char *next_in;
  333. size_t avail_out;
  334. unsigned char *next_out;
  335. unsigned char *buf;
  336. size_t bufsize;
  337. BrotliEncoderState *state;
  338. int mode; /* Encoder mode to use */
  339. int done;
  340. unsigned char *ptr;
  341. size_t count;
  342. } encode;
  343. } BIO_BROTLI_CTX;
  344. # define BROTLI_DEFAULT_BUFSIZE 1024
  345. static int bio_brotli_new(BIO *bi);
  346. static int bio_brotli_free(BIO *bi);
  347. static int bio_brotli_read(BIO *b, char *out, int outl);
  348. static int bio_brotli_write(BIO *b, const char *in, int inl);
  349. static long bio_brotli_ctrl(BIO *b, int cmd, long num, void *ptr);
  350. static long bio_brotli_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
  351. static const BIO_METHOD bio_meth_brotli = {
  352. BIO_TYPE_COMP,
  353. "brotli",
  354. /* TODO: Convert to new style write function */
  355. bwrite_conv,
  356. bio_brotli_write,
  357. /* TODO: Convert to new style read function */
  358. bread_conv,
  359. bio_brotli_read,
  360. NULL, /* bio_brotli_puts, */
  361. NULL, /* bio_brotli_gets, */
  362. bio_brotli_ctrl,
  363. bio_brotli_new,
  364. bio_brotli_free,
  365. bio_brotli_callback_ctrl
  366. };
  367. #endif
  368. const BIO_METHOD *BIO_f_brotli(void)
  369. {
  370. #ifndef OPENSSL_NO_BROTLI
  371. if (RUN_ONCE(&brotli_once, ossl_comp_brotli_init))
  372. return &bio_meth_brotli;
  373. #endif
  374. return NULL;
  375. }
  376. #ifndef OPENSSL_NO_BROTLI
  377. static int bio_brotli_new(BIO *bi)
  378. {
  379. BIO_BROTLI_CTX *ctx;
  380. # ifdef BROTLI_SHARED
  381. if (!RUN_ONCE(&brotli_once, ossl_comp_brotli_init)) {
  382. ERR_raise(ERR_LIB_COMP, COMP_R_BROTLI_NOT_SUPPORTED);
  383. return 0;
  384. }
  385. # endif
  386. ctx = OPENSSL_zalloc(sizeof(*ctx));
  387. if (ctx == NULL) {
  388. ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE);
  389. return 0;
  390. }
  391. ctx->decode.bufsize = BROTLI_DEFAULT_BUFSIZE;
  392. ctx->decode.state = BrotliDecoderCreateInstance(brotli_alloc, brotli_free, NULL);
  393. if (ctx->decode.state == NULL)
  394. goto err;
  395. ctx->encode.bufsize = BROTLI_DEFAULT_BUFSIZE;
  396. ctx->encode.state = BrotliEncoderCreateInstance(brotli_alloc, brotli_free, NULL);
  397. if (ctx->encode.state == NULL)
  398. goto err;
  399. ctx->encode.mode = BROTLI_DEFAULT_MODE;
  400. BIO_set_init(bi, 1);
  401. BIO_set_data(bi, ctx);
  402. return 1;
  403. err:
  404. ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE);
  405. BrotliDecoderDestroyInstance(ctx->decode.state);
  406. BrotliEncoderDestroyInstance(ctx->encode.state);
  407. OPENSSL_free(ctx);
  408. return 0;
  409. }
  410. static int bio_brotli_free(BIO *bi)
  411. {
  412. BIO_BROTLI_CTX *ctx;
  413. if (bi == NULL)
  414. return 0;
  415. ctx = BIO_get_data(bi);
  416. if (ctx != NULL) {
  417. BrotliDecoderDestroyInstance(ctx->decode.state);
  418. OPENSSL_free(ctx->decode.buf);
  419. BrotliEncoderDestroyInstance(ctx->encode.state);
  420. OPENSSL_free(ctx->encode.buf);
  421. OPENSSL_free(ctx);
  422. }
  423. BIO_set_data(bi, NULL);
  424. BIO_set_init(bi, 0);
  425. return 1;
  426. }
  427. static int bio_brotli_read(BIO *b, char *out, int outl)
  428. {
  429. BIO_BROTLI_CTX *ctx;
  430. BrotliDecoderResult bret;
  431. int ret;
  432. BIO *next = BIO_next(b);
  433. if (out == NULL || outl <= 0) {
  434. ERR_raise(ERR_LIB_COMP, ERR_R_PASSED_INVALID_ARGUMENT);
  435. return 0;
  436. }
  437. #if INT_MAX > SIZE_MAX
  438. if ((unsigned int)outl > SIZE_MAX) {
  439. ERR_raise(ERR_LIB_COMP, ERR_R_PASSED_INVALID_ARGUMENT);
  440. return 0;
  441. }
  442. #endif
  443. ctx = BIO_get_data(b);
  444. BIO_clear_retry_flags(b);
  445. if (ctx->decode.buf == NULL) {
  446. ctx->decode.buf = OPENSSL_malloc(ctx->decode.bufsize);
  447. if (ctx->decode.buf == NULL) {
  448. ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE);
  449. return 0;
  450. }
  451. ctx->decode.next_in = ctx->decode.buf;
  452. ctx->decode.avail_in = 0;
  453. }
  454. /* Copy output data directly to supplied buffer */
  455. ctx->decode.next_out = (unsigned char *)out;
  456. ctx->decode.avail_out = (size_t)outl;
  457. for (;;) {
  458. /* Decompress while data available */
  459. while (ctx->decode.avail_in > 0 || BrotliDecoderHasMoreOutput(ctx->decode.state)) {
  460. bret = BrotliDecoderDecompressStream(ctx->decode.state, &ctx->decode.avail_in, (const uint8_t**)&ctx->decode.next_in,
  461. &ctx->decode.avail_out, &ctx->decode.next_out, NULL);
  462. if (bret == BROTLI_DECODER_RESULT_ERROR) {
  463. ERR_raise(ERR_LIB_COMP, COMP_R_BROTLI_DECODE_ERROR);
  464. ERR_add_error_data(1, BrotliDecoderErrorString(BrotliDecoderGetErrorCode(ctx->decode.state)));
  465. return 0;
  466. }
  467. /* If EOF or we've read everything then return */
  468. if (BrotliDecoderIsFinished(ctx->decode.state) || ctx->decode.avail_out == 0)
  469. return (int)(outl - ctx->decode.avail_out);
  470. }
  471. /* If EOF */
  472. if (BrotliDecoderIsFinished(ctx->decode.state))
  473. return 0;
  474. /*
  475. * No data in input buffer try to read some in, if an error then
  476. * return the total data read.
  477. */
  478. ret = BIO_read(next, ctx->decode.buf, ctx->decode.bufsize);
  479. if (ret <= 0) {
  480. /* Total data read */
  481. int tot = outl - ctx->decode.avail_out;
  482. BIO_copy_next_retry(b);
  483. if (ret < 0)
  484. return (tot > 0) ? tot : ret;
  485. return tot;
  486. }
  487. ctx->decode.avail_in = ret;
  488. ctx->decode.next_in = ctx->decode.buf;
  489. }
  490. }
  491. static int bio_brotli_write(BIO *b, const char *in, int inl)
  492. {
  493. BIO_BROTLI_CTX *ctx;
  494. BROTLI_BOOL brret;
  495. int ret;
  496. BIO *next = BIO_next(b);
  497. if (in == NULL || inl <= 0) {
  498. ERR_raise(ERR_LIB_COMP, ERR_R_PASSED_INVALID_ARGUMENT);
  499. return 0;
  500. }
  501. #if INT_MAX > SIZE_MAX
  502. if ((unsigned int)inl > SIZE_MAX) {
  503. ERR_raise(ERR_LIB_COMP, ERR_R_PASSED_INVALID_ARGUMENT);
  504. return 0;
  505. }
  506. #endif
  507. ctx = BIO_get_data(b);
  508. if (ctx->encode.done)
  509. return 0;
  510. BIO_clear_retry_flags(b);
  511. if (ctx->encode.buf == NULL) {
  512. ctx->encode.buf = OPENSSL_malloc(ctx->encode.bufsize);
  513. if (ctx->encode.buf == NULL) {
  514. ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE);
  515. return 0;
  516. }
  517. ctx->encode.ptr = ctx->encode.buf;
  518. ctx->encode.count = 0;
  519. ctx->encode.next_out = ctx->encode.buf;
  520. ctx->encode.avail_out = ctx->encode.bufsize;
  521. }
  522. /* Obtain input data directly from supplied buffer */
  523. ctx->encode.next_in = (unsigned char *)in;
  524. ctx->encode.avail_in = (size_t)inl;
  525. for (;;) {
  526. /* If data in output buffer write it first */
  527. while (ctx->encode.count > 0) {
  528. ret = BIO_write(next, ctx->encode.ptr, ctx->encode.count);
  529. if (ret <= 0) {
  530. /* Total data written */
  531. int tot = inl - ctx->encode.avail_in;
  532. BIO_copy_next_retry(b);
  533. if (ret < 0)
  534. return (tot > 0) ? tot : ret;
  535. return tot;
  536. }
  537. ctx->encode.ptr += ret;
  538. ctx->encode.count -= ret;
  539. }
  540. /* Have we consumed all supplied data? */
  541. if (ctx->encode.avail_in == 0 && !BrotliEncoderHasMoreOutput(ctx->encode.state))
  542. return inl;
  543. /* Compress some more */
  544. /* Reset buffer */
  545. ctx->encode.ptr = ctx->encode.buf;
  546. ctx->encode.next_out = ctx->encode.buf;
  547. ctx->encode.avail_out = ctx->encode.bufsize;
  548. /* Compress some more */
  549. brret = BrotliEncoderCompressStream(ctx->encode.state, BROTLI_OPERATION_FLUSH, &ctx->encode.avail_in, (const uint8_t**)&ctx->encode.next_in,
  550. &ctx->encode.avail_out, &ctx->encode.next_out, NULL);
  551. if (brret != BROTLI_TRUE) {
  552. ERR_raise(ERR_LIB_COMP, COMP_R_BROTLI_ENCODE_ERROR);
  553. ERR_add_error_data(1, "brotli encoder error");
  554. return 0;
  555. }
  556. ctx->encode.count = ctx->encode.bufsize - ctx->encode.avail_out;
  557. }
  558. }
  559. static int bio_brotli_flush(BIO *b)
  560. {
  561. BIO_BROTLI_CTX *ctx;
  562. BROTLI_BOOL brret;
  563. int ret;
  564. BIO *next = BIO_next(b);
  565. ctx = BIO_get_data(b);
  566. /* If no data written or already flush show success */
  567. if (ctx->encode.buf == NULL || (ctx->encode.done && ctx->encode.count == 0))
  568. return 1;
  569. BIO_clear_retry_flags(b);
  570. /* No more input data */
  571. ctx->encode.next_in = NULL;
  572. ctx->encode.avail_in = 0;
  573. for (;;) {
  574. /* If data in output buffer write it first */
  575. while (ctx->encode.count > 0) {
  576. ret = BIO_write(next, ctx->encode.ptr, ctx->encode.count);
  577. if (ret <= 0) {
  578. BIO_copy_next_retry(b);
  579. return ret;
  580. }
  581. ctx->encode.ptr += ret;
  582. ctx->encode.count -= ret;
  583. }
  584. if (ctx->encode.done)
  585. return 1;
  586. /* Compress some more */
  587. /* Reset buffer */
  588. ctx->encode.ptr = ctx->encode.buf;
  589. ctx->encode.next_out = ctx->encode.buf;
  590. ctx->encode.avail_out = ctx->encode.bufsize;
  591. /* Compress some more */
  592. brret = BrotliEncoderCompressStream(ctx->encode.state, BROTLI_OPERATION_FINISH, &ctx->encode.avail_in,
  593. (const uint8_t**)&ctx->encode.next_in, &ctx->encode.avail_out, &ctx->encode.next_out, NULL);
  594. if (brret != BROTLI_TRUE) {
  595. ERR_raise(ERR_LIB_COMP, COMP_R_BROTLI_DECODE_ERROR);
  596. ERR_add_error_data(1, "brotli encoder error");
  597. return 0;
  598. }
  599. if (!BrotliEncoderHasMoreOutput(ctx->encode.state) && ctx->encode.avail_in == 0)
  600. ctx->encode.done = 1;
  601. ctx->encode.count = ctx->encode.bufsize - ctx->encode.avail_out;
  602. }
  603. }
  604. static long bio_brotli_ctrl(BIO *b, int cmd, long num, void *ptr)
  605. {
  606. BIO_BROTLI_CTX *ctx;
  607. unsigned char *tmp;
  608. int ret = 0, *ip;
  609. size_t ibs, obs;
  610. BIO *next = BIO_next(b);
  611. if (next == NULL)
  612. return 0;
  613. ctx = BIO_get_data(b);
  614. switch (cmd) {
  615. case BIO_CTRL_RESET:
  616. ctx->encode.count = 0;
  617. ctx->encode.done = 0;
  618. ret = 1;
  619. break;
  620. case BIO_CTRL_FLUSH:
  621. ret = bio_brotli_flush(b);
  622. if (ret > 0) {
  623. ret = BIO_flush(next);
  624. BIO_copy_next_retry(b);
  625. }
  626. break;
  627. case BIO_C_SET_BUFF_SIZE:
  628. ibs = ctx->decode.bufsize;
  629. obs = ctx->encode.bufsize;
  630. if (ptr != NULL) {
  631. ip = ptr;
  632. if (*ip == 0)
  633. ibs = (size_t)num;
  634. else
  635. obs = (size_t)num;
  636. } else {
  637. ibs = (size_t)num;
  638. obs = ibs;
  639. }
  640. if (ibs > 0 && ibs != ctx->decode.bufsize) {
  641. /* Do not free/alloc, only reallocate */
  642. if (ctx->decode.buf != NULL) {
  643. tmp = OPENSSL_realloc(ctx->decode.buf, ibs);
  644. if (tmp == NULL)
  645. return 0;
  646. ctx->decode.buf = tmp;
  647. }
  648. ctx->decode.bufsize = ibs;
  649. }
  650. if (obs > 0 && obs != ctx->encode.bufsize) {
  651. /* Do not free/alloc, only reallocate */
  652. if (ctx->encode.buf != NULL) {
  653. tmp = OPENSSL_realloc(ctx->encode.buf, obs);
  654. if (tmp == NULL)
  655. return 0;
  656. ctx->encode.buf = tmp;
  657. }
  658. ctx->encode.bufsize = obs;
  659. }
  660. ret = 1;
  661. break;
  662. case BIO_C_DO_STATE_MACHINE:
  663. BIO_clear_retry_flags(b);
  664. ret = BIO_ctrl(next, cmd, num, ptr);
  665. BIO_copy_next_retry(b);
  666. break;
  667. case BIO_CTRL_WPENDING:
  668. if (BrotliEncoderHasMoreOutput(ctx->encode.state))
  669. ret = 1;
  670. else
  671. ret = BIO_ctrl(next, cmd, num, ptr);
  672. break;
  673. case BIO_CTRL_PENDING:
  674. if (!BrotliDecoderIsFinished(ctx->decode.state))
  675. ret = 1;
  676. else
  677. ret = BIO_ctrl(next, cmd, num, ptr);
  678. break;
  679. default:
  680. ret = BIO_ctrl(next, cmd, num, ptr);
  681. break;
  682. }
  683. return ret;
  684. }
  685. static long bio_brotli_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
  686. {
  687. BIO *next = BIO_next(b);
  688. if (next == NULL)
  689. return 0;
  690. return BIO_callback_ctrl(next, cmd, fp);
  691. }
  692. #endif