1 /*
2 * Copyright 1998-2026 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
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <openssl/objects.h>
14 #include "internal/comp.h"
15 #include <openssl/err.h>
16 #include "crypto/cryptlib.h"
17 #include "internal/bio.h"
18 #include "internal/thread_once.h"
19 #include "comp_local.h"
20
21 COMP_METHOD *COMP_zlib(void);
22
23 #ifdef OPENSSL_NO_ZLIB
24 #undef ZLIB_SHARED
25 #else
26
27 #include <zlib.h>
28
29 static int zlib_stateful_init(COMP_CTX *ctx);
30 static void zlib_stateful_finish(COMP_CTX *ctx);
31 static ossl_ssize_t zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
32 size_t olen, unsigned char *in,
33 size_t ilen);
34 static ossl_ssize_t zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
35 size_t olen, unsigned char *in,
36 size_t ilen);
37
38 /* memory allocations functions for zlib initialisation */
zlib_zalloc(void * opaque,unsigned int no,unsigned int size)39 static void *zlib_zalloc(void *opaque, unsigned int no, unsigned int size)
40 {
41 void *p;
42
43 p = OPENSSL_zalloc(no * size);
44 return p;
45 }
46
zlib_zfree(void * opaque,void * address)47 static void zlib_zfree(void *opaque, void *address)
48 {
49 OPENSSL_free(address);
50 }
51
52 static COMP_METHOD zlib_stateful_method = {
53 NID_zlib_compression,
54 LN_zlib_compression,
55 zlib_stateful_init,
56 zlib_stateful_finish,
57 zlib_stateful_compress_block,
58 zlib_stateful_expand_block
59 };
60
61 /*
62 * When OpenSSL is built on Windows, we do not want to require that
63 * the ZLIB.DLL be available in order for the OpenSSL DLLs to
64 * work. Therefore, all ZLIB routines are loaded at run time
65 * and we do not link to a .LIB file when ZLIB_SHARED is set.
66 */
67 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
68 #include <windows.h>
69 #endif /* !(OPENSSL_SYS_WINDOWS || \
70 * OPENSSL_SYS_WIN32) */
71
72 #ifdef ZLIB_SHARED
73 #include "internal/dso.h"
74
75 /* Function pointers */
76 typedef int (*compress_ft)(Bytef *dest, uLongf *destLen,
77 const Bytef *source, uLong sourceLen);
78 typedef int (*uncompress_ft)(Bytef *dest, uLongf *destLen,
79 const Bytef *source, uLong sourceLen);
80 typedef int (*inflateEnd_ft)(z_streamp strm);
81 typedef int (*inflate_ft)(z_streamp strm, int flush);
82 typedef int (*inflateInit__ft)(z_streamp strm,
83 const char *version, int stream_size);
84 typedef int (*deflateEnd_ft)(z_streamp strm);
85 typedef int (*deflate_ft)(z_streamp strm, int flush);
86 typedef int (*deflateInit__ft)(z_streamp strm, int level,
87 const char *version, int stream_size);
88 typedef const char *(*zError__ft)(int err);
89 static compress_ft p_compress = NULL;
90 static uncompress_ft p_uncompress = NULL;
91 static inflateEnd_ft p_inflateEnd = NULL;
92 static inflate_ft p_inflate = NULL;
93 static inflateInit__ft p_inflateInit_ = NULL;
94 static deflateEnd_ft p_deflateEnd = NULL;
95 static deflate_ft p_deflate = NULL;
96 static deflateInit__ft p_deflateInit_ = NULL;
97 static zError__ft p_zError = NULL;
98
99 static DSO *zlib_dso = NULL;
100
101 #define compress p_compress
102 #define uncompress p_uncompress
103 #define inflateEnd p_inflateEnd
104 #define inflate p_inflate
105 #define inflateInit_ p_inflateInit_
106 #define deflateEnd p_deflateEnd
107 #define deflate p_deflate
108 #define deflateInit_ p_deflateInit_
109 #define zError p_zError
110 #endif /* ZLIB_SHARED */
111
112 struct zlib_state {
113 z_stream istream;
114 z_stream ostream;
115 };
116
zlib_stateful_init(COMP_CTX * ctx)117 static int zlib_stateful_init(COMP_CTX *ctx)
118 {
119 int err;
120 struct zlib_state *state = OPENSSL_zalloc(sizeof(*state));
121
122 if (state == NULL)
123 goto err;
124
125 state->istream.zalloc = zlib_zalloc;
126 state->istream.zfree = zlib_zfree;
127 state->istream.opaque = Z_NULL;
128 state->istream.next_in = Z_NULL;
129 state->istream.next_out = Z_NULL;
130 err = inflateInit_(&state->istream, ZLIB_VERSION, sizeof(z_stream));
131 if (err != Z_OK)
132 goto err;
133
134 state->ostream.zalloc = zlib_zalloc;
135 state->ostream.zfree = zlib_zfree;
136 state->ostream.opaque = Z_NULL;
137 state->ostream.next_in = Z_NULL;
138 state->ostream.next_out = Z_NULL;
139 err = deflateInit_(&state->ostream, Z_DEFAULT_COMPRESSION,
140 ZLIB_VERSION, sizeof(z_stream));
141 if (err != Z_OK)
142 goto err;
143
144 ctx->data = state;
145 return 1;
146 err:
147 OPENSSL_free(state);
148 return 0;
149 }
150
zlib_stateful_finish(COMP_CTX * ctx)151 static void zlib_stateful_finish(COMP_CTX *ctx)
152 {
153 struct zlib_state *state = ctx->data;
154 inflateEnd(&state->istream);
155 deflateEnd(&state->ostream);
156 OPENSSL_free(state);
157 }
158
zlib_stateful_compress_block(COMP_CTX * ctx,unsigned char * out,size_t olen,unsigned char * in,size_t ilen)159 static ossl_ssize_t zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
160 size_t olen, unsigned char *in,
161 size_t ilen)
162 {
163 int err = Z_OK;
164 struct zlib_state *state = ctx->data;
165
166 if (state == NULL)
167 return -1;
168
169 state->ostream.next_in = in;
170 state->ostream.avail_in = ilen;
171 state->ostream.next_out = out;
172 state->ostream.avail_out = olen;
173 if (ilen > 0)
174 err = deflate(&state->ostream, Z_SYNC_FLUSH);
175 if (err != Z_OK)
176 return -1;
177 if (state->ostream.avail_out > olen)
178 return -1;
179 return (ossl_ssize_t)(olen - state->ostream.avail_out);
180 }
181
zlib_stateful_expand_block(COMP_CTX * ctx,unsigned char * out,size_t olen,unsigned char * in,size_t ilen)182 static ossl_ssize_t zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
183 size_t olen, unsigned char *in,
184 size_t ilen)
185 {
186 int err = Z_OK;
187 struct zlib_state *state = ctx->data;
188
189 if (state == NULL)
190 return 0;
191
192 state->istream.next_in = in;
193 state->istream.avail_in = ilen;
194 state->istream.next_out = out;
195 state->istream.avail_out = olen;
196 if (ilen > 0)
197 err = inflate(&state->istream, Z_SYNC_FLUSH);
198 if (err != Z_OK)
199 return -1;
200 if (state->istream.avail_out > olen)
201 return -1;
202 return (ossl_ssize_t)(olen - state->istream.avail_out);
203 }
204
205 /* ONESHOT COMPRESSION/DECOMPRESSION */
206
zlib_oneshot_init(COMP_CTX * ctx)207 static int zlib_oneshot_init(COMP_CTX *ctx)
208 {
209 return 1;
210 }
211
zlib_oneshot_finish(COMP_CTX * ctx)212 static void zlib_oneshot_finish(COMP_CTX *ctx)
213 {
214 }
215
zlib_oneshot_compress_block(COMP_CTX * ctx,unsigned char * out,size_t olen,unsigned char * in,size_t ilen)216 static ossl_ssize_t zlib_oneshot_compress_block(COMP_CTX *ctx, unsigned char *out,
217 size_t olen, unsigned char *in,
218 size_t ilen)
219 {
220 uLongf out_size;
221
222 if (ilen == 0)
223 return 0;
224
225 /* zlib's uLongf defined as unsigned long FAR */
226 if (olen > ULONG_MAX)
227 return -1;
228 out_size = (uLongf)olen;
229
230 if (compress(out, &out_size, in, ilen) != Z_OK)
231 return -1;
232
233 if (out_size > OSSL_SSIZE_MAX)
234 return -1;
235 return (ossl_ssize_t)out_size;
236 }
237
zlib_oneshot_expand_block(COMP_CTX * ctx,unsigned char * out,size_t olen,unsigned char * in,size_t ilen)238 static ossl_ssize_t zlib_oneshot_expand_block(COMP_CTX *ctx, unsigned char *out,
239 size_t olen, unsigned char *in,
240 size_t ilen)
241 {
242 uLongf out_size;
243
244 if (ilen == 0)
245 return 0;
246
247 /* zlib's uLongf defined as unsigned long FAR */
248 if (olen > ULONG_MAX)
249 return -1;
250 out_size = (uLongf)olen;
251
252 if (uncompress(out, &out_size, in, ilen) != Z_OK)
253 return -1;
254
255 if (out_size > OSSL_SSIZE_MAX)
256 return -1;
257 return (ossl_ssize_t)out_size;
258 }
259
260 static COMP_METHOD zlib_oneshot_method = {
261 NID_zlib_compression,
262 LN_zlib_compression,
263 zlib_oneshot_init,
264 zlib_oneshot_finish,
265 zlib_oneshot_compress_block,
266 zlib_oneshot_expand_block
267 };
268
269 static CRYPTO_ONCE zlib_once = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_comp_zlib_init)270 DEFINE_RUN_ONCE_STATIC(ossl_comp_zlib_init)
271 {
272 #ifdef ZLIB_SHARED
273 /* LIBZ may be externally defined, and we should respect that value */
274 #ifndef LIBZ
275 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
276 #define LIBZ "ZLIB1"
277 #elif defined(OPENSSL_SYS_VMS)
278 #define LIBZ "LIBZ"
279 #else
280 #define LIBZ "z"
281 #endif
282 #endif
283
284 zlib_dso = DSO_load(NULL, LIBZ, NULL, 0);
285 if (zlib_dso != NULL) {
286 p_compress = (compress_ft)DSO_bind_func(zlib_dso, "compress");
287 p_uncompress = (uncompress_ft)DSO_bind_func(zlib_dso, "uncompress");
288 p_inflateEnd = (inflateEnd_ft)DSO_bind_func(zlib_dso, "inflateEnd");
289 p_inflate = (inflate_ft)DSO_bind_func(zlib_dso, "inflate");
290 p_inflateInit_ = (inflateInit__ft)DSO_bind_func(zlib_dso, "inflateInit_");
291 p_deflateEnd = (deflateEnd_ft)DSO_bind_func(zlib_dso, "deflateEnd");
292 p_deflate = (deflate_ft)DSO_bind_func(zlib_dso, "deflate");
293 p_deflateInit_ = (deflateInit__ft)DSO_bind_func(zlib_dso, "deflateInit_");
294 p_zError = (zError__ft)DSO_bind_func(zlib_dso, "zError");
295 }
296
297 if (p_compress == NULL || p_uncompress == NULL || p_inflateEnd == NULL
298 || p_inflate == NULL || p_inflateInit_ == NULL
299 || p_deflateEnd == NULL || p_deflate == NULL
300 || p_deflateInit_ == NULL || p_zError == NULL) {
301 ossl_comp_zlib_cleanup();
302 return 0;
303 }
304 #endif
305 return 1;
306 }
307 #endif
308
COMP_zlib(void)309 COMP_METHOD *COMP_zlib(void)
310 {
311 COMP_METHOD *meth = NULL;
312
313 #ifndef OPENSSL_NO_ZLIB
314 if (RUN_ONCE(&zlib_once, ossl_comp_zlib_init))
315 meth = &zlib_stateful_method;
316 #endif
317
318 return meth;
319 }
320
COMP_zlib_oneshot(void)321 COMP_METHOD *COMP_zlib_oneshot(void)
322 {
323 COMP_METHOD *meth = NULL;
324
325 #ifndef OPENSSL_NO_ZLIB
326 if (RUN_ONCE(&zlib_once, ossl_comp_zlib_init))
327 meth = &zlib_oneshot_method;
328 #endif
329
330 return meth;
331 }
332
333 /* Also called from OPENSSL_cleanup() */
ossl_comp_zlib_cleanup(void)334 void ossl_comp_zlib_cleanup(void)
335 {
336 #ifdef ZLIB_SHARED
337 DSO_free(zlib_dso);
338 zlib_dso = NULL;
339 #endif
340 }
341
342 #ifndef OPENSSL_NO_ZLIB
343
344 /* Zlib based compression/decompression filter BIO */
345
346 typedef struct {
347 unsigned char *ibuf; /* Input buffer */
348 int ibufsize; /* Buffer size */
349 z_stream zin; /* Input decompress context */
350 unsigned char *obuf; /* Output buffer */
351 int obufsize; /* Output buffer size */
352 unsigned char *optr; /* Position in output buffer */
353 int ocount; /* Amount of data in output buffer */
354 int odone; /* deflate EOF */
355 int comp_level; /* Compression level to use */
356 z_stream zout; /* Output compression context */
357 } BIO_ZLIB_CTX;
358
359 #define ZLIB_DEFAULT_BUFSIZE 1024
360
361 static int bio_zlib_new(BIO *bi);
362 static int bio_zlib_free(BIO *bi);
363 static int bio_zlib_read(BIO *b, char *out, int outl);
364 static int bio_zlib_write(BIO *b, const char *in, int inl);
365 static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr);
366 static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
367
368 static const BIO_METHOD bio_meth_zlib = {
369 BIO_TYPE_COMP,
370 "zlib",
371 bwrite_conv,
372 bio_zlib_write,
373 bread_conv,
374 bio_zlib_read,
375 NULL, /* bio_zlib_puts, */
376 NULL, /* bio_zlib_gets, */
377 bio_zlib_ctrl,
378 bio_zlib_new,
379 bio_zlib_free,
380 bio_zlib_callback_ctrl
381 };
382 #endif
383
BIO_f_zlib(void)384 const BIO_METHOD *BIO_f_zlib(void)
385 {
386 #ifndef OPENSSL_NO_ZLIB
387 if (RUN_ONCE(&zlib_once, ossl_comp_zlib_init))
388 return &bio_meth_zlib;
389 #endif
390 return NULL;
391 }
392
393 #ifndef OPENSSL_NO_ZLIB
bio_zlib_new(BIO * bi)394 static int bio_zlib_new(BIO *bi)
395 {
396 BIO_ZLIB_CTX *ctx;
397
398 #ifdef ZLIB_SHARED
399 if (!RUN_ONCE(&zlib_once, ossl_comp_zlib_init)) {
400 ERR_raise(ERR_LIB_COMP, COMP_R_ZLIB_NOT_SUPPORTED);
401 return 0;
402 }
403 #endif
404 ctx = OPENSSL_zalloc(sizeof(*ctx));
405 if (ctx == NULL)
406 return 0;
407 ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE;
408 ctx->obufsize = ZLIB_DEFAULT_BUFSIZE;
409 ctx->zin.zalloc = Z_NULL;
410 ctx->zin.zfree = Z_NULL;
411 ctx->zout.zalloc = Z_NULL;
412 ctx->zout.zfree = Z_NULL;
413 ctx->comp_level = Z_DEFAULT_COMPRESSION;
414 BIO_set_init(bi, 1);
415 BIO_set_data(bi, ctx);
416
417 return 1;
418 }
419
bio_zlib_free(BIO * bi)420 static int bio_zlib_free(BIO *bi)
421 {
422 BIO_ZLIB_CTX *ctx;
423
424 if (!bi)
425 return 0;
426 ctx = BIO_get_data(bi);
427 if (ctx->ibuf) {
428 /* Destroy decompress context */
429 inflateEnd(&ctx->zin);
430 OPENSSL_free(ctx->ibuf);
431 }
432 if (ctx->obuf) {
433 /* Destroy compress context */
434 deflateEnd(&ctx->zout);
435 OPENSSL_free(ctx->obuf);
436 }
437 OPENSSL_free(ctx);
438 BIO_set_data(bi, NULL);
439 BIO_set_init(bi, 0);
440
441 return 1;
442 }
443
bio_zlib_read(BIO * b,char * out,int outl)444 static int bio_zlib_read(BIO *b, char *out, int outl)
445 {
446 BIO_ZLIB_CTX *ctx;
447 int ret;
448 z_stream *zin;
449 BIO *next = BIO_next(b);
450
451 if (!out || !outl)
452 return 0;
453 ctx = BIO_get_data(b);
454 zin = &ctx->zin;
455 BIO_clear_retry_flags(b);
456 if (!ctx->ibuf) {
457 ctx->ibuf = OPENSSL_malloc(ctx->ibufsize);
458 if (ctx->ibuf == NULL)
459 return 0;
460 if ((ret = inflateInit(zin)) != Z_OK) {
461 ERR_raise_data(ERR_LIB_COMP, COMP_R_ZLIB_INFLATE_ERROR,
462 "zlib error: %s", zError(ret));
463 return 0;
464 }
465 zin->next_in = ctx->ibuf;
466 zin->avail_in = 0;
467 }
468
469 /* Copy output data directly to supplied buffer */
470 zin->next_out = (unsigned char *)out;
471 zin->avail_out = (unsigned int)outl;
472 for (;;) {
473 /* Decompress while data available */
474 while (zin->avail_in) {
475 ret = inflate(zin, 0);
476 if ((ret != Z_OK) && (ret != Z_STREAM_END)) {
477 ERR_raise_data(ERR_LIB_COMP, COMP_R_ZLIB_INFLATE_ERROR,
478 "zlib error: %s", zError(ret));
479 return 0;
480 }
481 /* If EOF or we've read everything then return */
482 if ((ret == Z_STREAM_END) || !zin->avail_out)
483 return outl - zin->avail_out;
484 }
485
486 /*
487 * No data in input buffer try to read some in, if an error then
488 * return the total data read.
489 */
490 ret = BIO_read(next, ctx->ibuf, ctx->ibufsize);
491 if (ret <= 0) {
492 /* Total data read */
493 int tot = outl - zin->avail_out;
494 BIO_copy_next_retry(b);
495 if (ret < 0)
496 return (tot > 0) ? tot : ret;
497 return tot;
498 }
499 zin->avail_in = ret;
500 zin->next_in = ctx->ibuf;
501 }
502 }
503
bio_zlib_write(BIO * b,const char * in,int inl)504 static int bio_zlib_write(BIO *b, const char *in, int inl)
505 {
506 BIO_ZLIB_CTX *ctx;
507 int ret;
508 z_stream *zout;
509 BIO *next = BIO_next(b);
510
511 if (!in || !inl)
512 return 0;
513 ctx = BIO_get_data(b);
514 if (ctx->odone)
515 return 0;
516 zout = &ctx->zout;
517 BIO_clear_retry_flags(b);
518 if (!ctx->obuf) {
519 ctx->obuf = OPENSSL_malloc(ctx->obufsize);
520 /* Need error here */
521 if (ctx->obuf == NULL)
522 return 0;
523 ctx->optr = ctx->obuf;
524 ctx->ocount = 0;
525 if ((ret = deflateInit(zout, ctx->comp_level)) != Z_OK) {
526 ERR_raise_data(ERR_LIB_COMP, COMP_R_ZLIB_DEFLATE_ERROR,
527 "zlib error: %s", zError(ret));
528 return 0;
529 }
530 zout->next_out = ctx->obuf;
531 zout->avail_out = ctx->obufsize;
532 }
533 /* Obtain input data directly from supplied buffer */
534 zout->next_in = (void *)in;
535 zout->avail_in = inl;
536 for (;;) {
537 /* If data in output buffer write it first */
538 while (ctx->ocount) {
539 ret = BIO_write(next, ctx->optr, ctx->ocount);
540 if (ret <= 0) {
541 /* Total data written */
542 int tot = inl - zout->avail_in;
543 BIO_copy_next_retry(b);
544 if (ret < 0)
545 return (tot > 0) ? tot : ret;
546 return tot;
547 }
548 ctx->optr += ret;
549 ctx->ocount -= ret;
550 }
551
552 /* Have we consumed all supplied data? */
553 if (!zout->avail_in)
554 return inl;
555
556 /* Compress some more */
557
558 /* Reset buffer */
559 ctx->optr = ctx->obuf;
560 zout->next_out = ctx->obuf;
561 zout->avail_out = ctx->obufsize;
562 /* Compress some more */
563 ret = deflate(zout, 0);
564 if (ret != Z_OK) {
565 ERR_raise_data(ERR_LIB_COMP, COMP_R_ZLIB_DEFLATE_ERROR,
566 "zlib error: %s", zError(ret));
567 return 0;
568 }
569 ctx->ocount = ctx->obufsize - zout->avail_out;
570 }
571 }
572
bio_zlib_flush(BIO * b)573 static int bio_zlib_flush(BIO *b)
574 {
575 BIO_ZLIB_CTX *ctx;
576 int ret;
577 z_stream *zout;
578 BIO *next = BIO_next(b);
579
580 ctx = BIO_get_data(b);
581 /* If no data written or already flush show success */
582 if (!ctx->obuf || (ctx->odone && !ctx->ocount))
583 return 1;
584 zout = &ctx->zout;
585 BIO_clear_retry_flags(b);
586 /* No more input data */
587 zout->next_in = NULL;
588 zout->avail_in = 0;
589 for (;;) {
590 /* If data in output buffer write it first */
591 while (ctx->ocount) {
592 ret = BIO_write(next, ctx->optr, ctx->ocount);
593 if (ret <= 0) {
594 BIO_copy_next_retry(b);
595 return ret;
596 }
597 ctx->optr += ret;
598 ctx->ocount -= ret;
599 }
600 if (ctx->odone)
601 return 1;
602
603 /* Compress some more */
604
605 /* Reset buffer */
606 ctx->optr = ctx->obuf;
607 zout->next_out = ctx->obuf;
608 zout->avail_out = ctx->obufsize;
609 /* Compress some more */
610 ret = deflate(zout, Z_FINISH);
611 if (ret == Z_STREAM_END)
612 ctx->odone = 1;
613 else if (ret != Z_OK) {
614 ERR_raise_data(ERR_LIB_COMP, COMP_R_ZLIB_DEFLATE_ERROR,
615 "zlib error: %s", zError(ret));
616 return 0;
617 }
618 ctx->ocount = ctx->obufsize - zout->avail_out;
619 }
620 }
621
bio_zlib_ctrl(BIO * b,int cmd,long num,void * ptr)622 static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
623 {
624 BIO_ZLIB_CTX *ctx;
625 int ret, *ip;
626 int ibs, obs;
627 BIO *next = BIO_next(b);
628
629 if (next == NULL)
630 return 0;
631 ctx = BIO_get_data(b);
632 switch (cmd) {
633
634 case BIO_CTRL_RESET:
635 ctx->ocount = 0;
636 ctx->odone = 0;
637 ret = 1;
638 break;
639
640 case BIO_CTRL_FLUSH:
641 ret = bio_zlib_flush(b);
642 if (ret > 0) {
643 ret = BIO_flush(next);
644 BIO_copy_next_retry(b);
645 }
646 break;
647
648 case BIO_C_SET_BUFF_SIZE:
649 ibs = -1;
650 obs = -1;
651 if (ptr != NULL) {
652 ip = ptr;
653 if (*ip == 0)
654 ibs = (int)num;
655 else
656 obs = (int)num;
657 } else {
658 ibs = (int)num;
659 obs = ibs;
660 }
661
662 if (ibs != -1) {
663 OPENSSL_free(ctx->ibuf);
664 ctx->ibuf = NULL;
665 ctx->ibufsize = ibs;
666 }
667
668 if (obs != -1) {
669 OPENSSL_free(ctx->obuf);
670 ctx->obuf = NULL;
671 ctx->obufsize = obs;
672 }
673 ret = 1;
674 break;
675
676 case BIO_C_DO_STATE_MACHINE:
677 BIO_clear_retry_flags(b);
678 ret = BIO_ctrl(next, cmd, num, ptr);
679 BIO_copy_next_retry(b);
680 break;
681
682 case BIO_CTRL_WPENDING:
683 if (ctx->obuf == NULL)
684 return 0;
685
686 if (ctx->odone) {
687 ret = ctx->ocount;
688 } else {
689 ret = ctx->ocount;
690 if (ret == 0)
691 /* Unknown amount pending but we are not finished */
692 ret = 1;
693 }
694 if (ret == 0)
695 ret = BIO_ctrl(next, cmd, num, ptr);
696 break;
697
698 case BIO_CTRL_PENDING:
699 ret = ctx->zin.avail_in;
700 if (ret == 0)
701 ret = BIO_ctrl(next, cmd, num, ptr);
702 break;
703
704 default:
705 ret = BIO_ctrl(next, cmd, num, ptr);
706 break;
707 }
708
709 return ret;
710 }
711
bio_zlib_callback_ctrl(BIO * b,int cmd,BIO_info_cb * fp)712 static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
713 {
714 BIO *next = BIO_next(b);
715
716 if (next == NULL)
717 return 0;
718 return BIO_callback_ctrl(next, cmd, fp);
719 }
720
721 #endif
722