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