diff options
Diffstat (limited to 'crypto/comp/c_zlib.c')
-rw-r--r-- | crypto/comp/c_zlib.c | 333 |
1 files changed, 94 insertions, 239 deletions
diff --git a/crypto/comp/c_zlib.c b/crypto/comp/c_zlib.c index 9c32614d3c70..d688deee5f23 100644 --- a/crypto/comp/c_zlib.c +++ b/crypto/comp/c_zlib.c @@ -1,9 +1,21 @@ +/* + * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/objects.h> -#include <openssl/comp.h> +#include "internal/comp.h" #include <openssl/err.h> +#include "internal/cryptlib_int.h" +#include "internal/bio.h" +#include "comp_lcl.h" COMP_METHOD *COMP_zlib(void); @@ -14,8 +26,6 @@ static COMP_METHOD zlib_method_nozlib = { NULL, NULL, NULL, - NULL, - NULL, }; #ifndef ZLIB @@ -33,14 +43,12 @@ static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, unsigned int olen, unsigned char *in, unsigned int ilen); -/* memory allocations functions for zlib intialization */ +/* memory allocations functions for zlib initialisation */ static void *zlib_zalloc(void *opaque, unsigned int no, unsigned int size) { void *p; - p = OPENSSL_malloc(no * size); - if (p) - memset(p, 0, no * size); + p = OPENSSL_zalloc(no * size); return p; } @@ -49,28 +57,6 @@ static void zlib_zfree(void *opaque, void *address) OPENSSL_free(address); } -# if 0 -static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, - unsigned int olen, unsigned char *in, - unsigned int ilen); -static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out, - unsigned int olen, unsigned char *in, - unsigned int ilen); - -static int zz_uncompress(Bytef *dest, uLongf * destLen, const Bytef *source, - uLong sourceLen); - -static COMP_METHOD zlib_stateless_method = { - NID_zlib_compression, - LN_zlib_compression, - NULL, - NULL, - zlib_compress_block, - zlib_expand_block, - NULL, - NULL, -}; -# endif static COMP_METHOD zlib_stateful_method = { NID_zlib_compression, @@ -78,9 +64,7 @@ static COMP_METHOD zlib_stateful_method = { zlib_stateful_init, zlib_stateful_finish, zlib_stateful_compress_block, - zlib_stateful_expand_block, - NULL, - NULL, + zlib_stateful_expand_block }; /* @@ -95,7 +79,7 @@ static COMP_METHOD zlib_stateful_method = { * OPENSSL_SYS_WIN32) */ # ifdef ZLIB_SHARED -# include <openssl/dso.h> +# include "internal/dso.h" /* Function pointers */ typedef int (*compress_ft) (Bytef *dest, uLongf * destLen, @@ -136,13 +120,10 @@ struct zlib_state { z_stream ostream; }; -static int zlib_stateful_ex_idx = -1; - static int zlib_stateful_init(COMP_CTX *ctx) { int err; - struct zlib_state *state = - (struct zlib_state *)OPENSSL_malloc(sizeof(struct zlib_state)); + struct zlib_state *state = OPENSSL_zalloc(sizeof(*state)); if (state == NULL) goto err; @@ -152,8 +133,6 @@ static int zlib_stateful_init(COMP_CTX *ctx) state->istream.opaque = Z_NULL; state->istream.next_in = Z_NULL; state->istream.next_out = Z_NULL; - state->istream.avail_in = 0; - state->istream.avail_out = 0; err = inflateInit_(&state->istream, ZLIB_VERSION, sizeof(z_stream)); if (err != Z_OK) goto err; @@ -163,31 +142,24 @@ static int zlib_stateful_init(COMP_CTX *ctx) state->ostream.opaque = Z_NULL; state->ostream.next_in = Z_NULL; state->ostream.next_out = Z_NULL; - state->ostream.avail_in = 0; - state->ostream.avail_out = 0; err = deflateInit_(&state->ostream, Z_DEFAULT_COMPRESSION, ZLIB_VERSION, sizeof(z_stream)); if (err != Z_OK) goto err; - CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data); - CRYPTO_set_ex_data(&ctx->ex_data, zlib_stateful_ex_idx, state); + ctx->data = state; return 1; err: - if (state) - OPENSSL_free(state); + OPENSSL_free(state); return 0; } static void zlib_stateful_finish(COMP_CTX *ctx) { - struct zlib_state *state = - (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, - zlib_stateful_ex_idx); + struct zlib_state *state = ctx->data; inflateEnd(&state->istream); deflateEnd(&state->ostream); OPENSSL_free(state); - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data); } static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, @@ -195,9 +167,7 @@ static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, unsigned int ilen) { int err = Z_OK; - struct zlib_state *state = - (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, - zlib_stateful_ex_idx); + struct zlib_state *state = ctx->data; if (state == NULL) return -1; @@ -210,11 +180,6 @@ static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, err = deflate(&state->ostream, Z_SYNC_FLUSH); if (err != Z_OK) return -1; -# ifdef DEBUG_ZLIB - fprintf(stderr, "compress(%4d)->%4d %s\n", - ilen, olen - state->ostream.avail_out, - (ilen != olen - state->ostream.avail_out) ? "zlib" : "clear"); -# endif return olen - state->ostream.avail_out; } @@ -223,10 +188,7 @@ static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, unsigned int ilen) { int err = Z_OK; - - struct zlib_state *state = - (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, - zlib_stateful_ex_idx); + struct zlib_state *state = ctx->data; if (state == NULL) return 0; @@ -239,105 +201,9 @@ static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, err = inflate(&state->istream, Z_SYNC_FLUSH); if (err != Z_OK) return -1; -# ifdef DEBUG_ZLIB - fprintf(stderr, "expand(%4d)->%4d %s\n", - ilen, olen - state->istream.avail_out, - (ilen != olen - state->istream.avail_out) ? "zlib" : "clear"); -# endif return olen - state->istream.avail_out; } -# if 0 -static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, - unsigned int olen, unsigned char *in, - unsigned int ilen) -{ - unsigned long l; - int i; - int clear = 1; - - if (ilen > 128) { - out[0] = 1; - l = olen - 1; - i = compress(&(out[1]), &l, in, (unsigned long)ilen); - if (i != Z_OK) - return (-1); - if (ilen > l) { - clear = 0; - l++; - } - } - if (clear) { - out[0] = 0; - memcpy(&(out[1]), in, ilen); - l = ilen + 1; - } -# ifdef DEBUG_ZLIB - fprintf(stderr, "compress(%4d)->%4d %s\n", - ilen, (int)l, (clear) ? "clear" : "zlib"); -# endif - return ((int)l); -} - -static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out, - unsigned int olen, unsigned char *in, - unsigned int ilen) -{ - unsigned long l; - int i; - - if (in[0]) { - l = olen; - i = zz_uncompress(out, &l, &(in[1]), (unsigned long)ilen - 1); - if (i != Z_OK) - return (-1); - } else { - memcpy(out, &(in[1]), ilen - 1); - l = ilen - 1; - } -# ifdef DEBUG_ZLIB - fprintf(stderr, "expand (%4d)->%4d %s\n", - ilen, (int)l, in[0] ? "zlib" : "clear"); -# endif - return ((int)l); -} - -static int zz_uncompress(Bytef *dest, uLongf * destLen, const Bytef *source, - uLong sourceLen) -{ - z_stream stream; - int err; - - stream.next_in = (Bytef *)source; - stream.avail_in = (uInt) sourceLen; - /* Check for source > 64K on 16-bit machine: */ - if ((uLong) stream.avail_in != sourceLen) - return Z_BUF_ERROR; - - stream.next_out = dest; - stream.avail_out = (uInt) * destLen; - if ((uLong) stream.avail_out != *destLen) - return Z_BUF_ERROR; - - stream.zalloc = (alloc_func) 0; - stream.zfree = (free_func) 0; - - err = inflateInit_(&stream, ZLIB_VERSION, sizeof(z_stream)); - if (err != Z_OK) - return err; - - err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - return err; - } - *destLen = stream.total_out; - - err = inflateEnd(&stream); - return err; -} -# endif - #endif COMP_METHOD *COMP_zlib(void) @@ -345,12 +211,19 @@ COMP_METHOD *COMP_zlib(void) COMP_METHOD *meth = &zlib_method_nozlib; #ifdef ZLIB_SHARED - if (!zlib_loaded) { -# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) - zlib_dso = DSO_load(NULL, "ZLIB1", NULL, 0); -# else - zlib_dso = DSO_load(NULL, "z", NULL, 0); + /* LIBZ may be externally defined, and we should respect that value */ +# ifndef LIBZ +# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) +# define LIBZ "ZLIB1" +# elif defined(OPENSSL_SYS_VMS) +# define LIBZ "LIBZ" +# else +# define LIBZ "z" +# endif # endif + + if (!zlib_loaded) { + zlib_dso = DSO_load(NULL, LIBZ, NULL, 0); if (zlib_dso != NULL) { p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress"); p_inflateEnd @@ -369,43 +242,27 @@ COMP_METHOD *COMP_zlib(void) && p_inflateInit_ && p_deflateEnd && p_deflate && p_deflateInit_ && p_zError) zlib_loaded++; + + if (!OPENSSL_init_crypto(OPENSSL_INIT_ZLIB, NULL)) { + comp_zlib_cleanup_int(); + return meth; + } + if (zlib_loaded) + meth = &zlib_stateful_method; } } #endif -#ifdef ZLIB_SHARED - if (zlib_loaded) +#if defined(ZLIB) + meth = &zlib_stateful_method; #endif -#if defined(ZLIB) || defined(ZLIB_SHARED) - { - /* - * init zlib_stateful_ex_idx here so that in a multi-process - * application it's enough to intialize openssl before forking (idx - * will be inherited in all the children) - */ - if (zlib_stateful_ex_idx == -1) { - CRYPTO_w_lock(CRYPTO_LOCK_COMP); - if (zlib_stateful_ex_idx == -1) - zlib_stateful_ex_idx = - CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP, - 0, NULL, NULL, NULL, NULL); - CRYPTO_w_unlock(CRYPTO_LOCK_COMP); - if (zlib_stateful_ex_idx == -1) - goto err; - } - meth = &zlib_stateful_method; - } - err: -#endif - - return (meth); + return meth; } -void COMP_zlib_cleanup(void) +void comp_zlib_cleanup_int(void) { #ifdef ZLIB_SHARED - if (zlib_dso != NULL) - DSO_free(zlib_dso); + DSO_free(zlib_dso); zlib_dso = NULL; #endif } @@ -434,22 +291,26 @@ static int bio_zlib_free(BIO *bi); static int bio_zlib_read(BIO *b, char *out, int outl); static int bio_zlib_write(BIO *b, const char *in, int inl); static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr); -static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp); +static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); -static BIO_METHOD bio_meth_zlib = { +static const BIO_METHOD bio_meth_zlib = { BIO_TYPE_COMP, "zlib", + /* TODO: Convert to new style write function */ + bwrite_conv, bio_zlib_write, + /* TODO: Convert to new style read function */ + bread_conv, bio_zlib_read, - NULL, - NULL, + NULL, /* bio_zlib_puts, */ + NULL, /* bio_zlib_gets, */ bio_zlib_ctrl, bio_zlib_new, bio_zlib_free, bio_zlib_callback_ctrl }; -BIO_METHOD *BIO_f_zlib(void) +const BIO_METHOD *BIO_f_zlib(void) { return &bio_meth_zlib; } @@ -464,32 +325,21 @@ static int bio_zlib_new(BIO *bi) return 0; } # endif - ctx = OPENSSL_malloc(sizeof(BIO_ZLIB_CTX)); - if (!ctx) { + ctx = OPENSSL_zalloc(sizeof(*ctx)); + if (ctx == NULL) { COMPerr(COMP_F_BIO_ZLIB_NEW, ERR_R_MALLOC_FAILURE); return 0; } - ctx->ibuf = NULL; - ctx->obuf = NULL; ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE; ctx->obufsize = ZLIB_DEFAULT_BUFSIZE; ctx->zin.zalloc = Z_NULL; ctx->zin.zfree = Z_NULL; - ctx->zin.next_in = NULL; - ctx->zin.avail_in = 0; - ctx->zin.next_out = NULL; - ctx->zin.avail_out = 0; ctx->zout.zalloc = Z_NULL; ctx->zout.zfree = Z_NULL; - ctx->zout.next_in = NULL; - ctx->zout.avail_in = 0; - ctx->zout.next_out = NULL; - ctx->zout.avail_out = 0; - ctx->odone = 0; ctx->comp_level = Z_DEFAULT_COMPRESSION; - bi->init = 1; - bi->ptr = (char *)ctx; - bi->flags = 0; + BIO_set_init(bi, 1); + BIO_set_data(bi, ctx); + return 1; } @@ -498,7 +348,7 @@ static int bio_zlib_free(BIO *bi) BIO_ZLIB_CTX *ctx; if (!bi) return 0; - ctx = (BIO_ZLIB_CTX *) bi->ptr; + ctx = BIO_get_data(bi); if (ctx->ibuf) { /* Destroy decompress context */ inflateEnd(&ctx->zin); @@ -510,9 +360,9 @@ static int bio_zlib_free(BIO *bi) OPENSSL_free(ctx->obuf); } OPENSSL_free(ctx); - bi->ptr = NULL; - bi->init = 0; - bi->flags = 0; + BIO_set_data(bi, NULL); + BIO_set_init(bi, 0); + return 1; } @@ -521,14 +371,16 @@ static int bio_zlib_read(BIO *b, char *out, int outl) BIO_ZLIB_CTX *ctx; int ret; z_stream *zin; + BIO *next = BIO_next(b); + if (!out || !outl) return 0; - ctx = (BIO_ZLIB_CTX *) b->ptr; + ctx = BIO_get_data(b); zin = &ctx->zin; BIO_clear_retry_flags(b); if (!ctx->ibuf) { ctx->ibuf = OPENSSL_malloc(ctx->ibufsize); - if (!ctx->ibuf) { + if (ctx->ibuf == NULL) { COMPerr(COMP_F_BIO_ZLIB_READ, ERR_R_MALLOC_FAILURE); return 0; } @@ -558,7 +410,7 @@ static int bio_zlib_read(BIO *b, char *out, int outl) * No data in input buffer try to read some in, if an error then * return the total data read. */ - ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize); + ret = BIO_read(next, ctx->ibuf, ctx->ibufsize); if (ret <= 0) { /* Total data read */ int tot = outl - zin->avail_out; @@ -577,9 +429,11 @@ static int bio_zlib_write(BIO *b, const char *in, int inl) BIO_ZLIB_CTX *ctx; int ret; z_stream *zout; + BIO *next = BIO_next(b); + if (!in || !inl) return 0; - ctx = (BIO_ZLIB_CTX *) b->ptr; + ctx = BIO_get_data(b); if (ctx->odone) return 0; zout = &ctx->zout; @@ -587,7 +441,7 @@ static int bio_zlib_write(BIO *b, const char *in, int inl) if (!ctx->obuf) { ctx->obuf = OPENSSL_malloc(ctx->obufsize); /* Need error here */ - if (!ctx->obuf) { + if (ctx->obuf == NULL) { COMPerr(COMP_F_BIO_ZLIB_WRITE, ERR_R_MALLOC_FAILURE); return 0; } @@ -603,7 +457,7 @@ static int bio_zlib_write(BIO *b, const char *in, int inl) for (;;) { /* If data in output buffer write it first */ while (ctx->ocount) { - ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); + ret = BIO_write(next, ctx->optr, ctx->ocount); if (ret <= 0) { /* Total data written */ int tot = inl - zout->avail_in; @@ -642,7 +496,9 @@ static int bio_zlib_flush(BIO *b) BIO_ZLIB_CTX *ctx; int ret; z_stream *zout; - ctx = (BIO_ZLIB_CTX *) b->ptr; + BIO *next = BIO_next(b); + + ctx = BIO_get_data(b); /* If no data written or already flush show success */ if (!ctx->obuf || (ctx->odone && !ctx->ocount)) return 1; @@ -654,7 +510,7 @@ static int bio_zlib_flush(BIO *b) for (;;) { /* If data in output buffer write it first */ while (ctx->ocount) { - ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); + ret = BIO_write(next, ctx->optr, ctx->ocount); if (ret <= 0) { BIO_copy_next_retry(b); return ret; @@ -689,9 +545,11 @@ static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) BIO_ZLIB_CTX *ctx; int ret, *ip; int ibs, obs; - if (!b->next_bio) + BIO *next = BIO_next(b); + + if (next == NULL) return 0; - ctx = (BIO_ZLIB_CTX *) b->ptr; + ctx = BIO_get_data(b); switch (cmd) { case BIO_CTRL_RESET: @@ -703,7 +561,7 @@ static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_FLUSH: ret = bio_zlib_flush(b); if (ret > 0) - ret = BIO_flush(b->next_bio); + ret = BIO_flush(next); break; case BIO_C_SET_BUFF_SIZE: @@ -721,18 +579,14 @@ static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) } if (ibs != -1) { - if (ctx->ibuf) { - OPENSSL_free(ctx->ibuf); - ctx->ibuf = NULL; - } + OPENSSL_free(ctx->ibuf); + ctx->ibuf = NULL; ctx->ibufsize = ibs; } if (obs != -1) { - if (ctx->obuf) { - OPENSSL_free(ctx->obuf); - ctx->obuf = NULL; - } + OPENSSL_free(ctx->obuf); + ctx->obuf = NULL; ctx->obufsize = obs; } ret = 1; @@ -740,12 +594,12 @@ static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_C_DO_STATE_MACHINE: BIO_clear_retry_flags(b); - ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + ret = BIO_ctrl(next, cmd, num, ptr); BIO_copy_next_retry(b); break; default: - ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + ret = BIO_ctrl(next, cmd, num, ptr); break; } @@ -753,11 +607,12 @@ static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) return ret; } -static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { - if (!b->next_bio) + BIO *next = BIO_next(b); + if (next == NULL) return 0; - return BIO_callback_ctrl(b->next_bio, cmd, fp); + return BIO_callback_ctrl(next, cmd, fp); } #endif |