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