155714Skris#include <stdio.h> 255714Skris#include <stdlib.h> 355714Skris#include <string.h> 455714Skris#include <openssl/objects.h> 555714Skris#include <openssl/comp.h> 6160814Ssimon#include <openssl/err.h> 755714Skris 8296341SdelphijCOMP_METHOD *COMP_zlib(void); 955714Skris 10296341Sdelphijstatic COMP_METHOD zlib_method_nozlib = { 11296341Sdelphij NID_undef, 12296341Sdelphij "(undef)", 13296341Sdelphij NULL, 14296341Sdelphij NULL, 15296341Sdelphij NULL, 16296341Sdelphij NULL, 17296341Sdelphij NULL, 18296341Sdelphij NULL, 19296341Sdelphij}; 2055714Skris 21109998Smarkm#ifndef ZLIB 22296341Sdelphij# undef ZLIB_SHARED 2355714Skris#else 2455714Skris 25296341Sdelphij# include <zlib.h> 2655714Skris 27160814Ssimonstatic int zlib_stateful_init(COMP_CTX *ctx); 28160814Ssimonstatic void zlib_stateful_finish(COMP_CTX *ctx); 29160814Ssimonstatic int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, 30296341Sdelphij unsigned int olen, unsigned char *in, 31296341Sdelphij unsigned int ilen); 32160814Ssimonstatic int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, 33296341Sdelphij unsigned int olen, unsigned char *in, 34296341Sdelphij unsigned int ilen); 35160814Ssimon 36167612Ssimon/* memory allocations functions for zlib intialization */ 37296341Sdelphijstatic void *zlib_zalloc(void *opaque, unsigned int no, unsigned int size) 38167612Ssimon{ 39296341Sdelphij void *p; 40296341Sdelphij 41296341Sdelphij p = OPENSSL_malloc(no * size); 42296341Sdelphij if (p) 43296341Sdelphij memset(p, 0, no * size); 44296341Sdelphij return p; 45167612Ssimon} 46167612Ssimon 47296341Sdelphijstatic void zlib_zfree(void *opaque, void *address) 48167612Ssimon{ 49296341Sdelphij OPENSSL_free(address); 50167612Ssimon} 51167612Ssimon 52296341Sdelphij# if 0 5355714Skrisstatic int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, 54296341Sdelphij unsigned int olen, unsigned char *in, 55296341Sdelphij unsigned int ilen); 5655714Skrisstatic int zlib_expand_block(COMP_CTX *ctx, unsigned char *out, 57296341Sdelphij unsigned int olen, unsigned char *in, 58296341Sdelphij unsigned int ilen); 5955714Skris 60296341Sdelphijstatic int zz_uncompress(Bytef *dest, uLongf * destLen, const Bytef *source, 61296341Sdelphij uLong sourceLen); 6255714Skris 63296341Sdelphijstatic COMP_METHOD zlib_stateless_method = { 64296341Sdelphij NID_zlib_compression, 65296341Sdelphij LN_zlib_compression, 66296341Sdelphij NULL, 67296341Sdelphij NULL, 68296341Sdelphij zlib_compress_block, 69296341Sdelphij zlib_expand_block, 70296341Sdelphij NULL, 71296341Sdelphij NULL, 72296341Sdelphij}; 73296341Sdelphij# endif 7455714Skris 75296341Sdelphijstatic COMP_METHOD zlib_stateful_method = { 76296341Sdelphij NID_zlib_compression, 77296341Sdelphij LN_zlib_compression, 78296341Sdelphij zlib_stateful_init, 79296341Sdelphij zlib_stateful_finish, 80296341Sdelphij zlib_stateful_compress_block, 81296341Sdelphij zlib_stateful_expand_block, 82296341Sdelphij NULL, 83296341Sdelphij NULL, 84296341Sdelphij}; 85160814Ssimon 86296341Sdelphij/* 87109998Smarkm * When OpenSSL is built on Windows, we do not want to require that 88109998Smarkm * the ZLIB.DLL be available in order for the OpenSSL DLLs to 89109998Smarkm * work. Therefore, all ZLIB routines are loaded at run time 90160814Ssimon * and we do not link to a .LIB file when ZLIB_SHARED is set. 91109998Smarkm */ 92296341Sdelphij# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) 93296341Sdelphij# include <windows.h> 94296341Sdelphij# endif /* !(OPENSSL_SYS_WINDOWS || 95296341Sdelphij * OPENSSL_SYS_WIN32) */ 96109998Smarkm 97296341Sdelphij# ifdef ZLIB_SHARED 98296341Sdelphij# include <openssl/dso.h> 99109998Smarkm 100109998Smarkm/* Function pointers */ 101296341Sdelphijtypedef int (*compress_ft) (Bytef *dest, uLongf * destLen, 102296341Sdelphij const Bytef *source, uLong sourceLen); 103296341Sdelphijtypedef int (*inflateEnd_ft) (z_streamp strm); 104296341Sdelphijtypedef int (*inflate_ft) (z_streamp strm, int flush); 105296341Sdelphijtypedef int (*inflateInit__ft) (z_streamp strm, 106296341Sdelphij const char *version, int stream_size); 107296341Sdelphijtypedef int (*deflateEnd_ft) (z_streamp strm); 108296341Sdelphijtypedef int (*deflate_ft) (z_streamp strm, int flush); 109296341Sdelphijtypedef int (*deflateInit__ft) (z_streamp strm, int level, 110296341Sdelphij const char *version, int stream_size); 111296341Sdelphijtypedef const char *(*zError__ft) (int err); 112296341Sdelphijstatic compress_ft p_compress = NULL; 113296341Sdelphijstatic inflateEnd_ft p_inflateEnd = NULL; 114296341Sdelphijstatic inflate_ft p_inflate = NULL; 115296341Sdelphijstatic inflateInit__ft p_inflateInit_ = NULL; 116296341Sdelphijstatic deflateEnd_ft p_deflateEnd = NULL; 117296341Sdelphijstatic deflate_ft p_deflate = NULL; 118296341Sdelphijstatic deflateInit__ft p_deflateInit_ = NULL; 119296341Sdelphijstatic zError__ft p_zError = NULL; 120109998Smarkm 121109998Smarkmstatic int zlib_loaded = 0; /* only attempt to init func pts once */ 122109998Smarkmstatic DSO *zlib_dso = NULL; 123109998Smarkm 124296341Sdelphij# define compress p_compress 125296341Sdelphij# define inflateEnd p_inflateEnd 126296341Sdelphij# define inflate p_inflate 127296341Sdelphij# define inflateInit_ p_inflateInit_ 128296341Sdelphij# define deflateEnd p_deflateEnd 129296341Sdelphij# define deflate p_deflate 130296341Sdelphij# define deflateInit_ p_deflateInit_ 131296341Sdelphij# define zError p_zError 132296341Sdelphij# endif /* ZLIB_SHARED */ 133109998Smarkm 134296341Sdelphijstruct zlib_state { 135296341Sdelphij z_stream istream; 136296341Sdelphij z_stream ostream; 137296341Sdelphij}; 138160814Ssimon 139160814Ssimonstatic int zlib_stateful_ex_idx = -1; 140160814Ssimon 141160814Ssimonstatic int zlib_stateful_init(COMP_CTX *ctx) 142296341Sdelphij{ 143296341Sdelphij int err; 144296341Sdelphij struct zlib_state *state = 145296341Sdelphij (struct zlib_state *)OPENSSL_malloc(sizeof(struct zlib_state)); 146160814Ssimon 147296341Sdelphij if (state == NULL) 148296341Sdelphij goto err; 149160814Ssimon 150296341Sdelphij state->istream.zalloc = zlib_zalloc; 151296341Sdelphij state->istream.zfree = zlib_zfree; 152296341Sdelphij state->istream.opaque = Z_NULL; 153296341Sdelphij state->istream.next_in = Z_NULL; 154296341Sdelphij state->istream.next_out = Z_NULL; 155296341Sdelphij state->istream.avail_in = 0; 156296341Sdelphij state->istream.avail_out = 0; 157296341Sdelphij err = inflateInit_(&state->istream, ZLIB_VERSION, sizeof(z_stream)); 158296341Sdelphij if (err != Z_OK) 159296341Sdelphij goto err; 160160814Ssimon 161296341Sdelphij state->ostream.zalloc = zlib_zalloc; 162296341Sdelphij state->ostream.zfree = zlib_zfree; 163296341Sdelphij state->ostream.opaque = Z_NULL; 164296341Sdelphij state->ostream.next_in = Z_NULL; 165296341Sdelphij state->ostream.next_out = Z_NULL; 166296341Sdelphij state->ostream.avail_in = 0; 167296341Sdelphij state->ostream.avail_out = 0; 168296341Sdelphij err = deflateInit_(&state->ostream, Z_DEFAULT_COMPRESSION, 169296341Sdelphij ZLIB_VERSION, sizeof(z_stream)); 170296341Sdelphij if (err != Z_OK) 171296341Sdelphij goto err; 172160814Ssimon 173296341Sdelphij CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data); 174296341Sdelphij CRYPTO_set_ex_data(&ctx->ex_data, zlib_stateful_ex_idx, state); 175296341Sdelphij return 1; 176160814Ssimon err: 177296341Sdelphij if (state) 178296341Sdelphij OPENSSL_free(state); 179296341Sdelphij return 0; 180296341Sdelphij} 181160814Ssimon 182160814Ssimonstatic void zlib_stateful_finish(COMP_CTX *ctx) 183296341Sdelphij{ 184296341Sdelphij struct zlib_state *state = 185296341Sdelphij (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, 186296341Sdelphij zlib_stateful_ex_idx); 187296341Sdelphij inflateEnd(&state->istream); 188296341Sdelphij deflateEnd(&state->ostream); 189296341Sdelphij OPENSSL_free(state); 190296341Sdelphij CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data); 191296341Sdelphij} 192160814Ssimon 193160814Ssimonstatic int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, 194296341Sdelphij unsigned int olen, unsigned char *in, 195296341Sdelphij unsigned int ilen) 196296341Sdelphij{ 197296341Sdelphij int err = Z_OK; 198296341Sdelphij struct zlib_state *state = 199296341Sdelphij (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, 200296341Sdelphij zlib_stateful_ex_idx); 201160814Ssimon 202296341Sdelphij if (state == NULL) 203296341Sdelphij return -1; 204160814Ssimon 205296341Sdelphij state->ostream.next_in = in; 206296341Sdelphij state->ostream.avail_in = ilen; 207296341Sdelphij state->ostream.next_out = out; 208296341Sdelphij state->ostream.avail_out = olen; 209296341Sdelphij if (ilen > 0) 210296341Sdelphij err = deflate(&state->ostream, Z_SYNC_FLUSH); 211296341Sdelphij if (err != Z_OK) 212296341Sdelphij return -1; 213296341Sdelphij# ifdef DEBUG_ZLIB 214296341Sdelphij fprintf(stderr, "compress(%4d)->%4d %s\n", 215296341Sdelphij ilen, olen - state->ostream.avail_out, 216296341Sdelphij (ilen != olen - state->ostream.avail_out) ? "zlib" : "clear"); 217296341Sdelphij# endif 218296341Sdelphij return olen - state->ostream.avail_out; 219296341Sdelphij} 220160814Ssimon 221160814Ssimonstatic int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, 222296341Sdelphij unsigned int olen, unsigned char *in, 223296341Sdelphij unsigned int ilen) 224296341Sdelphij{ 225296341Sdelphij int err = Z_OK; 226160814Ssimon 227296341Sdelphij struct zlib_state *state = 228296341Sdelphij (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, 229296341Sdelphij zlib_stateful_ex_idx); 230160814Ssimon 231296341Sdelphij if (state == NULL) 232296341Sdelphij return 0; 233160814Ssimon 234296341Sdelphij state->istream.next_in = in; 235296341Sdelphij state->istream.avail_in = ilen; 236296341Sdelphij state->istream.next_out = out; 237296341Sdelphij state->istream.avail_out = olen; 238296341Sdelphij if (ilen > 0) 239296341Sdelphij err = inflate(&state->istream, Z_SYNC_FLUSH); 240296341Sdelphij if (err != Z_OK) 241296341Sdelphij return -1; 242296341Sdelphij# ifdef DEBUG_ZLIB 243296341Sdelphij fprintf(stderr, "expand(%4d)->%4d %s\n", 244296341Sdelphij ilen, olen - state->istream.avail_out, 245296341Sdelphij (ilen != olen - state->istream.avail_out) ? "zlib" : "clear"); 246296341Sdelphij# endif 247296341Sdelphij return olen - state->istream.avail_out; 248296341Sdelphij} 249160814Ssimon 250296341Sdelphij# if 0 25155714Skrisstatic int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, 252296341Sdelphij unsigned int olen, unsigned char *in, 253296341Sdelphij unsigned int ilen) 254296341Sdelphij{ 255296341Sdelphij unsigned long l; 256296341Sdelphij int i; 257296341Sdelphij int clear = 1; 25855714Skris 259296341Sdelphij if (ilen > 128) { 260296341Sdelphij out[0] = 1; 261296341Sdelphij l = olen - 1; 262296341Sdelphij i = compress(&(out[1]), &l, in, (unsigned long)ilen); 263296341Sdelphij if (i != Z_OK) 264296341Sdelphij return (-1); 265296341Sdelphij if (ilen > l) { 266296341Sdelphij clear = 0; 267296341Sdelphij l++; 268296341Sdelphij } 269296341Sdelphij } 270296341Sdelphij if (clear) { 271296341Sdelphij out[0] = 0; 272296341Sdelphij memcpy(&(out[1]), in, ilen); 273296341Sdelphij l = ilen + 1; 274296341Sdelphij } 275296341Sdelphij# ifdef DEBUG_ZLIB 276296341Sdelphij fprintf(stderr, "compress(%4d)->%4d %s\n", 277296341Sdelphij ilen, (int)l, (clear) ? "clear" : "zlib"); 278296341Sdelphij# endif 279296341Sdelphij return ((int)l); 280296341Sdelphij} 28155714Skris 28255714Skrisstatic int zlib_expand_block(COMP_CTX *ctx, unsigned char *out, 283296341Sdelphij unsigned int olen, unsigned char *in, 284296341Sdelphij unsigned int ilen) 285296341Sdelphij{ 286296341Sdelphij unsigned long l; 287296341Sdelphij int i; 28855714Skris 289296341Sdelphij if (in[0]) { 290296341Sdelphij l = olen; 291296341Sdelphij i = zz_uncompress(out, &l, &(in[1]), (unsigned long)ilen - 1); 292296341Sdelphij if (i != Z_OK) 293296341Sdelphij return (-1); 294296341Sdelphij } else { 295296341Sdelphij memcpy(out, &(in[1]), ilen - 1); 296296341Sdelphij l = ilen - 1; 297296341Sdelphij } 298296341Sdelphij# ifdef DEBUG_ZLIB 299296341Sdelphij fprintf(stderr, "expand (%4d)->%4d %s\n", 300296341Sdelphij ilen, (int)l, in[0] ? "zlib" : "clear"); 301296341Sdelphij# endif 302296341Sdelphij return ((int)l); 303296341Sdelphij} 30455714Skris 305296341Sdelphijstatic int zz_uncompress(Bytef *dest, uLongf * destLen, const Bytef *source, 306296341Sdelphij uLong sourceLen) 30755714Skris{ 30855714Skris z_stream stream; 30955714Skris int err; 31055714Skris 311296341Sdelphij stream.next_in = (Bytef *)source; 312296341Sdelphij stream.avail_in = (uInt) sourceLen; 31355714Skris /* Check for source > 64K on 16-bit machine: */ 314296341Sdelphij if ((uLong) stream.avail_in != sourceLen) 315296341Sdelphij return Z_BUF_ERROR; 31655714Skris 31755714Skris stream.next_out = dest; 318296341Sdelphij stream.avail_out = (uInt) * destLen; 319296341Sdelphij if ((uLong) stream.avail_out != *destLen) 320296341Sdelphij return Z_BUF_ERROR; 32155714Skris 322296341Sdelphij stream.zalloc = (alloc_func) 0; 323296341Sdelphij stream.zfree = (free_func) 0; 32455714Skris 325296341Sdelphij err = inflateInit_(&stream, ZLIB_VERSION, sizeof(z_stream)); 326296341Sdelphij if (err != Z_OK) 327296341Sdelphij return err; 32855714Skris 32955714Skris err = inflate(&stream, Z_FINISH); 33055714Skris if (err != Z_STREAM_END) { 33155714Skris inflateEnd(&stream); 33255714Skris return err; 33355714Skris } 33455714Skris *destLen = stream.total_out; 33555714Skris 33655714Skris err = inflateEnd(&stream); 33755714Skris return err; 33855714Skris} 339296341Sdelphij# endif 34055714Skris 34155714Skris#endif 34255714Skris 34355714SkrisCOMP_METHOD *COMP_zlib(void) 344296341Sdelphij{ 345296341Sdelphij COMP_METHOD *meth = &zlib_method_nozlib; 346109998Smarkm 347109998Smarkm#ifdef ZLIB_SHARED 348296341Sdelphij if (!zlib_loaded) { 349296341Sdelphij# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) 350296341Sdelphij zlib_dso = DSO_load(NULL, "ZLIB1", NULL, 0); 351296341Sdelphij# else 352296341Sdelphij zlib_dso = DSO_load(NULL, "z", NULL, 0); 353296341Sdelphij# endif 354296341Sdelphij if (zlib_dso != NULL) { 355296341Sdelphij p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress"); 356296341Sdelphij p_inflateEnd 357296341Sdelphij = (inflateEnd_ft) DSO_bind_func(zlib_dso, "inflateEnd"); 358296341Sdelphij p_inflate = (inflate_ft) DSO_bind_func(zlib_dso, "inflate"); 359296341Sdelphij p_inflateInit_ 360296341Sdelphij = (inflateInit__ft) DSO_bind_func(zlib_dso, "inflateInit_"); 361296341Sdelphij p_deflateEnd 362296341Sdelphij = (deflateEnd_ft) DSO_bind_func(zlib_dso, "deflateEnd"); 363296341Sdelphij p_deflate = (deflate_ft) DSO_bind_func(zlib_dso, "deflate"); 364296341Sdelphij p_deflateInit_ 365296341Sdelphij = (deflateInit__ft) DSO_bind_func(zlib_dso, "deflateInit_"); 366296341Sdelphij p_zError = (zError__ft) DSO_bind_func(zlib_dso, "zError"); 367160814Ssimon 368296341Sdelphij if (p_compress && p_inflateEnd && p_inflate 369296341Sdelphij && p_inflateInit_ && p_deflateEnd 370296341Sdelphij && p_deflate && p_deflateInit_ && p_zError) 371296341Sdelphij zlib_loaded++; 372296341Sdelphij } 373296341Sdelphij } 374109998Smarkm#endif 375160814Ssimon#ifdef ZLIB_SHARED 376296341Sdelphij if (zlib_loaded) 377160814Ssimon#endif 378109998Smarkm#if defined(ZLIB) || defined(ZLIB_SHARED) 379296341Sdelphij { 380296341Sdelphij /* 381296341Sdelphij * init zlib_stateful_ex_idx here so that in a multi-process 382296341Sdelphij * application it's enough to intialize openssl before forking (idx 383296341Sdelphij * will be inherited in all the children) 384296341Sdelphij */ 385296341Sdelphij if (zlib_stateful_ex_idx == -1) { 386296341Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_COMP); 387296341Sdelphij if (zlib_stateful_ex_idx == -1) 388296341Sdelphij zlib_stateful_ex_idx = 389296341Sdelphij CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP, 390296341Sdelphij 0, NULL, NULL, NULL, NULL); 391296341Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_COMP); 392296341Sdelphij if (zlib_stateful_ex_idx == -1) 393296341Sdelphij goto err; 394296341Sdelphij } 395296341Sdelphij 396296341Sdelphij meth = &zlib_stateful_method; 397296341Sdelphij } 398296341Sdelphij err: 399109998Smarkm#endif 400109998Smarkm 401296341Sdelphij return (meth); 402296341Sdelphij} 40355714Skris 404194206Ssimonvoid COMP_zlib_cleanup(void) 405296341Sdelphij{ 406194206Ssimon#ifdef ZLIB_SHARED 407296341Sdelphij if (zlib_dso) 408296341Sdelphij DSO_free(zlib_dso); 409194206Ssimon#endif 410296341Sdelphij} 411194206Ssimon 412194206Ssimon#ifdef ZLIB 413194206Ssimon 414194206Ssimon/* Zlib based compression/decompression filter BIO */ 415194206Ssimon 416296341Sdelphijtypedef struct { 417296341Sdelphij unsigned char *ibuf; /* Input buffer */ 418296341Sdelphij int ibufsize; /* Buffer size */ 419296341Sdelphij z_stream zin; /* Input decompress context */ 420296341Sdelphij unsigned char *obuf; /* Output buffer */ 421296341Sdelphij int obufsize; /* Output buffer size */ 422296341Sdelphij unsigned char *optr; /* Position in output buffer */ 423296341Sdelphij int ocount; /* Amount of data in output buffer */ 424296341Sdelphij int odone; /* deflate EOF */ 425296341Sdelphij int comp_level; /* Compression level to use */ 426296341Sdelphij z_stream zout; /* Output compression context */ 427296341Sdelphij} BIO_ZLIB_CTX; 428194206Ssimon 429296341Sdelphij# define ZLIB_DEFAULT_BUFSIZE 1024 430194206Ssimon 431194206Ssimonstatic int bio_zlib_new(BIO *bi); 432194206Ssimonstatic int bio_zlib_free(BIO *bi); 433194206Ssimonstatic int bio_zlib_read(BIO *b, char *out, int outl); 434194206Ssimonstatic int bio_zlib_write(BIO *b, const char *in, int inl); 435194206Ssimonstatic long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr); 436194206Ssimonstatic long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp); 437194206Ssimon 438296341Sdelphijstatic BIO_METHOD bio_meth_zlib = { 439296341Sdelphij BIO_TYPE_COMP, 440296341Sdelphij "zlib", 441296341Sdelphij bio_zlib_write, 442296341Sdelphij bio_zlib_read, 443296341Sdelphij NULL, 444296341Sdelphij NULL, 445296341Sdelphij bio_zlib_ctrl, 446296341Sdelphij bio_zlib_new, 447296341Sdelphij bio_zlib_free, 448296341Sdelphij bio_zlib_callback_ctrl 449296341Sdelphij}; 450194206Ssimon 451194206SsimonBIO_METHOD *BIO_f_zlib(void) 452296341Sdelphij{ 453296341Sdelphij return &bio_meth_zlib; 454296341Sdelphij} 455194206Ssimon 456194206Ssimonstatic int bio_zlib_new(BIO *bi) 457296341Sdelphij{ 458296341Sdelphij BIO_ZLIB_CTX *ctx; 459296341Sdelphij# ifdef ZLIB_SHARED 460296341Sdelphij (void)COMP_zlib(); 461296341Sdelphij if (!zlib_loaded) { 462296341Sdelphij COMPerr(COMP_F_BIO_ZLIB_NEW, COMP_R_ZLIB_NOT_SUPPORTED); 463296341Sdelphij return 0; 464296341Sdelphij } 465296341Sdelphij# endif 466296341Sdelphij ctx = OPENSSL_malloc(sizeof(BIO_ZLIB_CTX)); 467296341Sdelphij if (!ctx) { 468296341Sdelphij COMPerr(COMP_F_BIO_ZLIB_NEW, ERR_R_MALLOC_FAILURE); 469296341Sdelphij return 0; 470296341Sdelphij } 471296341Sdelphij ctx->ibuf = NULL; 472296341Sdelphij ctx->obuf = NULL; 473296341Sdelphij ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE; 474296341Sdelphij ctx->obufsize = ZLIB_DEFAULT_BUFSIZE; 475296341Sdelphij ctx->zin.zalloc = Z_NULL; 476296341Sdelphij ctx->zin.zfree = Z_NULL; 477296341Sdelphij ctx->zin.next_in = NULL; 478296341Sdelphij ctx->zin.avail_in = 0; 479296341Sdelphij ctx->zin.next_out = NULL; 480296341Sdelphij ctx->zin.avail_out = 0; 481296341Sdelphij ctx->zout.zalloc = Z_NULL; 482296341Sdelphij ctx->zout.zfree = Z_NULL; 483296341Sdelphij ctx->zout.next_in = NULL; 484296341Sdelphij ctx->zout.avail_in = 0; 485296341Sdelphij ctx->zout.next_out = NULL; 486296341Sdelphij ctx->zout.avail_out = 0; 487296341Sdelphij ctx->odone = 0; 488296341Sdelphij ctx->comp_level = Z_DEFAULT_COMPRESSION; 489296341Sdelphij bi->init = 1; 490296341Sdelphij bi->ptr = (char *)ctx; 491296341Sdelphij bi->flags = 0; 492296341Sdelphij return 1; 493296341Sdelphij} 494194206Ssimon 495194206Ssimonstatic int bio_zlib_free(BIO *bi) 496296341Sdelphij{ 497296341Sdelphij BIO_ZLIB_CTX *ctx; 498296341Sdelphij if (!bi) 499296341Sdelphij return 0; 500296341Sdelphij ctx = (BIO_ZLIB_CTX *) bi->ptr; 501296341Sdelphij if (ctx->ibuf) { 502296341Sdelphij /* Destroy decompress context */ 503296341Sdelphij inflateEnd(&ctx->zin); 504296341Sdelphij OPENSSL_free(ctx->ibuf); 505296341Sdelphij } 506296341Sdelphij if (ctx->obuf) { 507296341Sdelphij /* Destroy compress context */ 508296341Sdelphij deflateEnd(&ctx->zout); 509296341Sdelphij OPENSSL_free(ctx->obuf); 510296341Sdelphij } 511296341Sdelphij OPENSSL_free(ctx); 512296341Sdelphij bi->ptr = NULL; 513296341Sdelphij bi->init = 0; 514296341Sdelphij bi->flags = 0; 515296341Sdelphij return 1; 516296341Sdelphij} 517194206Ssimon 518194206Ssimonstatic int bio_zlib_read(BIO *b, char *out, int outl) 519296341Sdelphij{ 520296341Sdelphij BIO_ZLIB_CTX *ctx; 521296341Sdelphij int ret; 522296341Sdelphij z_stream *zin; 523296341Sdelphij if (!out || !outl) 524296341Sdelphij return 0; 525296341Sdelphij ctx = (BIO_ZLIB_CTX *) b->ptr; 526296341Sdelphij zin = &ctx->zin; 527296341Sdelphij BIO_clear_retry_flags(b); 528296341Sdelphij if (!ctx->ibuf) { 529296341Sdelphij ctx->ibuf = OPENSSL_malloc(ctx->ibufsize); 530296341Sdelphij if (!ctx->ibuf) { 531296341Sdelphij COMPerr(COMP_F_BIO_ZLIB_READ, ERR_R_MALLOC_FAILURE); 532296341Sdelphij return 0; 533296341Sdelphij } 534296341Sdelphij inflateInit(zin); 535296341Sdelphij zin->next_in = ctx->ibuf; 536296341Sdelphij zin->avail_in = 0; 537296341Sdelphij } 538194206Ssimon 539296341Sdelphij /* Copy output data directly to supplied buffer */ 540296341Sdelphij zin->next_out = (unsigned char *)out; 541296341Sdelphij zin->avail_out = (unsigned int)outl; 542296341Sdelphij for (;;) { 543296341Sdelphij /* Decompress while data available */ 544296341Sdelphij while (zin->avail_in) { 545296341Sdelphij ret = inflate(zin, 0); 546296341Sdelphij if ((ret != Z_OK) && (ret != Z_STREAM_END)) { 547296341Sdelphij COMPerr(COMP_F_BIO_ZLIB_READ, COMP_R_ZLIB_INFLATE_ERROR); 548296341Sdelphij ERR_add_error_data(2, "zlib error:", zError(ret)); 549296341Sdelphij return 0; 550296341Sdelphij } 551296341Sdelphij /* If EOF or we've read everything then return */ 552296341Sdelphij if ((ret == Z_STREAM_END) || !zin->avail_out) 553296341Sdelphij return outl - zin->avail_out; 554296341Sdelphij } 555194206Ssimon 556296341Sdelphij /* 557296341Sdelphij * No data in input buffer try to read some in, if an error then 558296341Sdelphij * return the total data read. 559296341Sdelphij */ 560296341Sdelphij ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize); 561296341Sdelphij if (ret <= 0) { 562296341Sdelphij /* Total data read */ 563296341Sdelphij int tot = outl - zin->avail_out; 564296341Sdelphij BIO_copy_next_retry(b); 565296341Sdelphij if (ret < 0) 566296341Sdelphij return (tot > 0) ? tot : ret; 567296341Sdelphij return tot; 568296341Sdelphij } 569296341Sdelphij zin->avail_in = ret; 570296341Sdelphij zin->next_in = ctx->ibuf; 571296341Sdelphij } 572296341Sdelphij} 573194206Ssimon 574194206Ssimonstatic int bio_zlib_write(BIO *b, const char *in, int inl) 575296341Sdelphij{ 576296341Sdelphij BIO_ZLIB_CTX *ctx; 577296341Sdelphij int ret; 578296341Sdelphij z_stream *zout; 579296341Sdelphij if (!in || !inl) 580296341Sdelphij return 0; 581296341Sdelphij ctx = (BIO_ZLIB_CTX *) b->ptr; 582296341Sdelphij if (ctx->odone) 583296341Sdelphij return 0; 584296341Sdelphij zout = &ctx->zout; 585296341Sdelphij BIO_clear_retry_flags(b); 586296341Sdelphij if (!ctx->obuf) { 587296341Sdelphij ctx->obuf = OPENSSL_malloc(ctx->obufsize); 588296341Sdelphij /* Need error here */ 589296341Sdelphij if (!ctx->obuf) { 590296341Sdelphij COMPerr(COMP_F_BIO_ZLIB_WRITE, ERR_R_MALLOC_FAILURE); 591296341Sdelphij return 0; 592296341Sdelphij } 593296341Sdelphij ctx->optr = ctx->obuf; 594296341Sdelphij ctx->ocount = 0; 595296341Sdelphij deflateInit(zout, ctx->comp_level); 596296341Sdelphij zout->next_out = ctx->obuf; 597296341Sdelphij zout->avail_out = ctx->obufsize; 598296341Sdelphij } 599296341Sdelphij /* Obtain input data directly from supplied buffer */ 600296341Sdelphij zout->next_in = (void *)in; 601296341Sdelphij zout->avail_in = inl; 602296341Sdelphij for (;;) { 603296341Sdelphij /* If data in output buffer write it first */ 604296341Sdelphij while (ctx->ocount) { 605296341Sdelphij ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); 606296341Sdelphij if (ret <= 0) { 607296341Sdelphij /* Total data written */ 608296341Sdelphij int tot = inl - zout->avail_in; 609296341Sdelphij BIO_copy_next_retry(b); 610296341Sdelphij if (ret < 0) 611296341Sdelphij return (tot > 0) ? tot : ret; 612296341Sdelphij return tot; 613296341Sdelphij } 614296341Sdelphij ctx->optr += ret; 615296341Sdelphij ctx->ocount -= ret; 616296341Sdelphij } 617194206Ssimon 618296341Sdelphij /* Have we consumed all supplied data? */ 619296341Sdelphij if (!zout->avail_in) 620296341Sdelphij return inl; 621194206Ssimon 622296341Sdelphij /* Compress some more */ 623194206Ssimon 624296341Sdelphij /* Reset buffer */ 625296341Sdelphij ctx->optr = ctx->obuf; 626296341Sdelphij zout->next_out = ctx->obuf; 627296341Sdelphij zout->avail_out = ctx->obufsize; 628296341Sdelphij /* Compress some more */ 629296341Sdelphij ret = deflate(zout, 0); 630296341Sdelphij if (ret != Z_OK) { 631296341Sdelphij COMPerr(COMP_F_BIO_ZLIB_WRITE, COMP_R_ZLIB_DEFLATE_ERROR); 632296341Sdelphij ERR_add_error_data(2, "zlib error:", zError(ret)); 633296341Sdelphij return 0; 634296341Sdelphij } 635296341Sdelphij ctx->ocount = ctx->obufsize - zout->avail_out; 636296341Sdelphij } 637296341Sdelphij} 638194206Ssimon 639194206Ssimonstatic int bio_zlib_flush(BIO *b) 640296341Sdelphij{ 641296341Sdelphij BIO_ZLIB_CTX *ctx; 642296341Sdelphij int ret; 643296341Sdelphij z_stream *zout; 644296341Sdelphij ctx = (BIO_ZLIB_CTX *) b->ptr; 645296341Sdelphij /* If no data written or already flush show success */ 646296341Sdelphij if (!ctx->obuf || (ctx->odone && !ctx->ocount)) 647296341Sdelphij return 1; 648296341Sdelphij zout = &ctx->zout; 649296341Sdelphij BIO_clear_retry_flags(b); 650296341Sdelphij /* No more input data */ 651296341Sdelphij zout->next_in = NULL; 652296341Sdelphij zout->avail_in = 0; 653296341Sdelphij for (;;) { 654296341Sdelphij /* If data in output buffer write it first */ 655296341Sdelphij while (ctx->ocount) { 656296341Sdelphij ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); 657296341Sdelphij if (ret <= 0) { 658296341Sdelphij BIO_copy_next_retry(b); 659296341Sdelphij return ret; 660296341Sdelphij } 661296341Sdelphij ctx->optr += ret; 662296341Sdelphij ctx->ocount -= ret; 663296341Sdelphij } 664296341Sdelphij if (ctx->odone) 665296341Sdelphij return 1; 666194206Ssimon 667296341Sdelphij /* Compress some more */ 668194206Ssimon 669296341Sdelphij /* Reset buffer */ 670296341Sdelphij ctx->optr = ctx->obuf; 671296341Sdelphij zout->next_out = ctx->obuf; 672296341Sdelphij zout->avail_out = ctx->obufsize; 673296341Sdelphij /* Compress some more */ 674296341Sdelphij ret = deflate(zout, Z_FINISH); 675296341Sdelphij if (ret == Z_STREAM_END) 676296341Sdelphij ctx->odone = 1; 677296341Sdelphij else if (ret != Z_OK) { 678296341Sdelphij COMPerr(COMP_F_BIO_ZLIB_FLUSH, COMP_R_ZLIB_DEFLATE_ERROR); 679296341Sdelphij ERR_add_error_data(2, "zlib error:", zError(ret)); 680296341Sdelphij return 0; 681296341Sdelphij } 682296341Sdelphij ctx->ocount = ctx->obufsize - zout->avail_out; 683296341Sdelphij } 684296341Sdelphij} 685194206Ssimon 686194206Ssimonstatic long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) 687296341Sdelphij{ 688296341Sdelphij BIO_ZLIB_CTX *ctx; 689296341Sdelphij int ret, *ip; 690296341Sdelphij int ibs, obs; 691296341Sdelphij if (!b->next_bio) 692296341Sdelphij return 0; 693296341Sdelphij ctx = (BIO_ZLIB_CTX *) b->ptr; 694296341Sdelphij switch (cmd) { 695194206Ssimon 696296341Sdelphij case BIO_CTRL_RESET: 697296341Sdelphij ctx->ocount = 0; 698296341Sdelphij ctx->odone = 0; 699296341Sdelphij ret = 1; 700296341Sdelphij break; 701194206Ssimon 702296341Sdelphij case BIO_CTRL_FLUSH: 703296341Sdelphij ret = bio_zlib_flush(b); 704296341Sdelphij if (ret > 0) 705296341Sdelphij ret = BIO_flush(b->next_bio); 706296341Sdelphij break; 707194206Ssimon 708296341Sdelphij case BIO_C_SET_BUFF_SIZE: 709296341Sdelphij ibs = -1; 710296341Sdelphij obs = -1; 711296341Sdelphij if (ptr != NULL) { 712296341Sdelphij ip = ptr; 713296341Sdelphij if (*ip == 0) 714296341Sdelphij ibs = (int)num; 715296341Sdelphij else 716296341Sdelphij obs = (int)num; 717296341Sdelphij } else { 718296341Sdelphij ibs = (int)num; 719296341Sdelphij obs = ibs; 720296341Sdelphij } 721194206Ssimon 722296341Sdelphij if (ibs != -1) { 723296341Sdelphij if (ctx->ibuf) { 724296341Sdelphij OPENSSL_free(ctx->ibuf); 725296341Sdelphij ctx->ibuf = NULL; 726296341Sdelphij } 727296341Sdelphij ctx->ibufsize = ibs; 728296341Sdelphij } 729194206Ssimon 730296341Sdelphij if (obs != -1) { 731296341Sdelphij if (ctx->obuf) { 732296341Sdelphij OPENSSL_free(ctx->obuf); 733296341Sdelphij ctx->obuf = NULL; 734296341Sdelphij } 735296341Sdelphij ctx->obufsize = obs; 736296341Sdelphij } 737296341Sdelphij ret = 1; 738296341Sdelphij break; 739194206Ssimon 740296341Sdelphij case BIO_C_DO_STATE_MACHINE: 741296341Sdelphij BIO_clear_retry_flags(b); 742296341Sdelphij ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 743296341Sdelphij BIO_copy_next_retry(b); 744296341Sdelphij break; 745194206Ssimon 746296341Sdelphij default: 747296341Sdelphij ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 748296341Sdelphij break; 749238405Sjkim 750296341Sdelphij } 751194206Ssimon 752296341Sdelphij return ret; 753296341Sdelphij} 754194206Ssimon 755194206Ssimonstatic long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 756296341Sdelphij{ 757296341Sdelphij if (!b->next_bio) 758296341Sdelphij return 0; 759296341Sdelphij return BIO_callback_ctrl(b->next_bio, cmd, fp); 760296341Sdelphij} 761194206Ssimon 762194206Ssimon#endif 763