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