1 /* $OpenBSD: c_zlib.c,v 1.17 2014/11/03 16:58:28 tedu Exp $ */
5 #include <openssl/objects.h>
6 #include <openssl/comp.h>
7 #include <openssl/err.h>
9 COMP_METHOD *COMP_zlib(void );
11 static COMP_METHOD zlib_method_nozlib = {
20 static int zlib_stateful_init(COMP_CTX *ctx);
21 static void zlib_stateful_finish(COMP_CTX *ctx);
22 static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
23 unsigned int olen, unsigned char *in, unsigned int ilen);
24 static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
25 unsigned int olen, unsigned char *in, unsigned int ilen);
28 /* memory allocations functions for zlib intialization */
30 zlib_zalloc(void* opaque, unsigned int no, unsigned int size)
32 return calloc(no, size);
36 zlib_zfree(void* opaque, void* address)
41 static COMP_METHOD zlib_stateful_method = {
42 .type = NID_zlib_compression,
43 .name = LN_zlib_compression,
44 .init = zlib_stateful_init,
45 .finish = zlib_stateful_finish,
46 .compress = zlib_stateful_compress_block,
47 .expand = zlib_stateful_expand_block
55 static int zlib_stateful_ex_idx = -1;
58 zlib_stateful_init(COMP_CTX *ctx)
61 struct zlib_state *state = malloc(sizeof(struct zlib_state));
66 state->istream.zalloc = zlib_zalloc;
67 state->istream.zfree = zlib_zfree;
68 state->istream.opaque = Z_NULL;
69 state->istream.next_in = Z_NULL;
70 state->istream.next_out = Z_NULL;
71 state->istream.avail_in = 0;
72 state->istream.avail_out = 0;
73 err = inflateInit_(&state->istream, ZLIB_VERSION, sizeof(z_stream));
77 state->ostream.zalloc = zlib_zalloc;
78 state->ostream.zfree = zlib_zfree;
79 state->ostream.opaque = Z_NULL;
80 state->ostream.next_in = Z_NULL;
81 state->ostream.next_out = Z_NULL;
82 state->ostream.avail_in = 0;
83 state->ostream.avail_out = 0;
84 err = deflateInit_(&state->ostream, Z_DEFAULT_COMPRESSION,
85 ZLIB_VERSION, sizeof(z_stream));
89 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data);
90 CRYPTO_set_ex_data(&ctx->ex_data, zlib_stateful_ex_idx, state);
99 zlib_stateful_finish(COMP_CTX *ctx)
101 struct zlib_state *state =
102 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
103 zlib_stateful_ex_idx);
105 inflateEnd(&state->istream);
106 deflateEnd(&state->ostream);
108 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data);
112 zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
113 unsigned int olen, unsigned char *in, unsigned int ilen)
116 struct zlib_state *state =
117 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
118 zlib_stateful_ex_idx);
123 state->ostream.next_in = in;
124 state->ostream.avail_in = ilen;
125 state->ostream.next_out = out;
126 state->ostream.avail_out = olen;
128 err = deflate(&state->ostream, Z_SYNC_FLUSH);
133 fprintf(stderr, "compress(%4d)->%4d %s\n",
134 ilen, olen - state->ostream.avail_out,
135 (ilen != olen - state->ostream.avail_out)?"zlib":"clear");
138 return olen - state->ostream.avail_out;
142 zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
143 unsigned int olen, unsigned char *in, unsigned int ilen)
147 struct zlib_state *state =
148 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
149 zlib_stateful_ex_idx);
154 state->istream.next_in = in;
155 state->istream.avail_in = ilen;
156 state->istream.next_out = out;
157 state->istream.avail_out = olen;
159 err = inflate(&state->istream, Z_SYNC_FLUSH);
164 fprintf(stderr, "expand(%4d)->%4d %s\n",
165 ilen, olen - state->istream.avail_out,
166 (ilen != olen - state->istream.avail_out)?"zlib":"clear");
169 return olen - state->istream.avail_out;
177 COMP_METHOD *meth = &zlib_method_nozlib;
181 /* init zlib_stateful_ex_idx here so that in a multi-process
182 * application it's enough to intialize openssl before forking
183 * (idx will be inherited in all the children) */
184 if (zlib_stateful_ex_idx == -1) {
185 CRYPTO_w_lock(CRYPTO_LOCK_COMP);
186 if (zlib_stateful_ex_idx == -1)
187 zlib_stateful_ex_idx =
188 CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP,
189 0, NULL, NULL, NULL, NULL);
190 CRYPTO_w_unlock(CRYPTO_LOCK_COMP);
191 if (zlib_stateful_ex_idx == -1)
195 meth = &zlib_stateful_method;
205 COMP_zlib_cleanup(void)
211 /* Zlib based compression/decompression filter BIO */
214 unsigned char *ibuf; /* Input buffer */
215 int ibufsize; /* Buffer size */
216 z_stream zin; /* Input decompress context */
217 unsigned char *obuf; /* Output buffer */
218 int obufsize; /* Output buffer size */
219 unsigned char *optr; /* Position in output buffer */
220 int ocount; /* Amount of data in output buffer */
221 int odone; /* deflate EOF */
222 int comp_level; /* Compression level to use */
223 z_stream zout; /* Output compression context */
226 #define ZLIB_DEFAULT_BUFSIZE 1024
228 static int bio_zlib_new(BIO *bi);
229 static int bio_zlib_free(BIO *bi);
230 static int bio_zlib_read(BIO *b, char *out, int outl);
231 static int bio_zlib_write(BIO *b, const char *in, int inl);
232 static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr);
233 static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp);
235 static BIO_METHOD bio_meth_zlib = {
236 .type = BIO_TYPE_COMP,
238 .bwrite = bio_zlib_write,
239 .bread = bio_zlib_read,
240 .ctrl = bio_zlib_ctrl,
241 .create = bio_zlib_new,
242 .destroy = bio_zlib_free,
243 .callback_ctrl = bio_zlib_callback_ctrl
249 return &bio_meth_zlib;
254 bio_zlib_new(BIO *bi)
258 ctx = malloc(sizeof(BIO_ZLIB_CTX));
260 COMPerr(COMP_F_BIO_ZLIB_NEW, ERR_R_MALLOC_FAILURE);
265 ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE;
266 ctx->obufsize = ZLIB_DEFAULT_BUFSIZE;
267 ctx->zin.zalloc = Z_NULL;
268 ctx->zin.zfree = Z_NULL;
269 ctx->zin.next_in = NULL;
270 ctx->zin.avail_in = 0;
271 ctx->zin.next_out = NULL;
272 ctx->zin.avail_out = 0;
273 ctx->zout.zalloc = Z_NULL;
274 ctx->zout.zfree = Z_NULL;
275 ctx->zout.next_in = NULL;
276 ctx->zout.avail_in = 0;
277 ctx->zout.next_out = NULL;
278 ctx->zout.avail_out = 0;
280 ctx->comp_level = Z_DEFAULT_COMPRESSION;
282 bi->ptr = (char *)ctx;
288 bio_zlib_free(BIO *bi)
294 ctx = (BIO_ZLIB_CTX *)bi->ptr;
296 /* Destroy decompress context */
297 inflateEnd(&ctx->zin);
301 /* Destroy compress context */
302 deflateEnd(&ctx->zout);
313 bio_zlib_read(BIO *b, char *out, int outl)
321 ctx = (BIO_ZLIB_CTX *)b->ptr;
323 BIO_clear_retry_flags(b);
325 ctx->ibuf = malloc(ctx->ibufsize);
327 COMPerr(COMP_F_BIO_ZLIB_READ, ERR_R_MALLOC_FAILURE);
331 zin->next_in = ctx->ibuf;
335 /* Copy output data directly to supplied buffer */
336 zin->next_out = (unsigned char *)out;
337 zin->avail_out = (unsigned int)outl;
339 /* Decompress while data available */
340 while (zin->avail_in) {
341 ret = inflate(zin, 0);
342 if ((ret != Z_OK) && (ret != Z_STREAM_END)) {
343 COMPerr(COMP_F_BIO_ZLIB_READ,
344 COMP_R_ZLIB_INFLATE_ERROR);
345 ERR_asprintf_error_data("zlib error:%s",
349 /* If EOF or we've read everything then return */
350 if ((ret == Z_STREAM_END) || !zin->avail_out)
351 return outl - zin->avail_out;
354 /* No data in input buffer try to read some in,
355 * if an error then return the total data read.
357 ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize);
359 /* Total data read */
360 int tot = outl - zin->avail_out;
361 BIO_copy_next_retry(b);
363 return (tot > 0) ? tot : ret;
367 zin->next_in = ctx->ibuf;
372 bio_zlib_write(BIO *b, const char *in, int inl)
380 ctx = (BIO_ZLIB_CTX *)b->ptr;
384 BIO_clear_retry_flags(b);
386 ctx->obuf = malloc(ctx->obufsize);
387 /* Need error here */
389 COMPerr(COMP_F_BIO_ZLIB_WRITE, ERR_R_MALLOC_FAILURE);
392 ctx->optr = ctx->obuf;
394 deflateInit(zout, ctx->comp_level);
395 zout->next_out = ctx->obuf;
396 zout->avail_out = ctx->obufsize;
398 /* Obtain input data directly from supplied buffer */
399 zout->next_in = (void *)in;
400 zout->avail_in = inl;
402 /* If data in output buffer write it first */
403 while (ctx->ocount) {
404 ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
406 /* Total data written */
407 int tot = inl - zout->avail_in;
408 BIO_copy_next_retry(b);
410 return (tot > 0) ? tot : ret;
417 /* Have we consumed all supplied data? */
421 /* Compress some more */
424 ctx->optr = ctx->obuf;
425 zout->next_out = ctx->obuf;
426 zout->avail_out = ctx->obufsize;
427 /* Compress some more */
428 ret = deflate(zout, 0);
430 COMPerr(COMP_F_BIO_ZLIB_WRITE,
431 COMP_R_ZLIB_DEFLATE_ERROR);
432 ERR_asprintf_error_data("zlib error:%s", zError(ret));
435 ctx->ocount = ctx->obufsize - zout->avail_out;
440 bio_zlib_flush(BIO *b)
446 ctx = (BIO_ZLIB_CTX *)b->ptr;
447 /* If no data written or already flush show success */
448 if (!ctx->obuf || (ctx->odone && !ctx->ocount))
451 BIO_clear_retry_flags(b);
452 /* No more input data */
453 zout->next_in = NULL;
456 /* If data in output buffer write it first */
457 while (ctx->ocount) {
458 ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
460 BIO_copy_next_retry(b);
469 /* Compress some more */
472 ctx->optr = ctx->obuf;
473 zout->next_out = ctx->obuf;
474 zout->avail_out = ctx->obufsize;
475 /* Compress some more */
476 ret = deflate(zout, Z_FINISH);
477 if (ret == Z_STREAM_END)
479 else if (ret != Z_OK) {
480 COMPerr(COMP_F_BIO_ZLIB_FLUSH,
481 COMP_R_ZLIB_DEFLATE_ERROR);
482 ERR_asprintf_error_data("zlib error:%s", zError(ret));
485 ctx->ocount = ctx->obufsize - zout->avail_out;
490 bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
497 ctx = (BIO_ZLIB_CTX *)b->ptr;
507 ret = bio_zlib_flush(b);
509 ret = BIO_flush(b->next_bio);
512 case BIO_C_SET_BUFF_SIZE:
540 case BIO_C_DO_STATE_MACHINE:
541 BIO_clear_retry_flags(b);
542 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
543 BIO_copy_next_retry(b);
547 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
557 bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
561 return BIO_callback_ctrl(b->next_bio, cmd, fp);