update libressl to v2.7.4
[unleashed.git] / lib / libcrypto / comp / c_zlib.c
blob0cdbb205a4462c1823ad7683a83a18d4f9dbe845
1 /* $OpenBSD: c_zlib.c,v 1.20 2018/03/17 16:20:01 beck Exp $ */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
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 = {
12 .type = NID_undef,
13 .name = "(undef)"
16 #ifdef ZLIB
18 #include <zlib.h>
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 */
29 static void*
30 zlib_zalloc(void* opaque, unsigned int no, unsigned int size)
32 return calloc(no, size);
35 static void
36 zlib_zfree(void* opaque, void* address)
38 free(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
50 struct zlib_state {
51 z_stream istream;
52 z_stream ostream;
55 static int zlib_stateful_ex_idx = -1;
57 static int
58 zlib_stateful_init(COMP_CTX *ctx)
60 int err;
61 struct zlib_state *state = malloc(sizeof(struct zlib_state));
63 if (state == NULL)
64 goto err;
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));
74 if (err != Z_OK)
75 goto err;
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));
86 if (err != Z_OK)
87 goto err;
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);
91 return 1;
93 err:
94 free(state);
95 return 0;
98 static void
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);
107 free(state);
108 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data);
111 static int
112 zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
113 unsigned int olen, unsigned char *in, unsigned int ilen)
115 int err = Z_OK;
116 struct zlib_state *state =
117 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
118 zlib_stateful_ex_idx);
120 if (state == NULL)
121 return -1;
123 state->ostream.next_in = in;
124 state->ostream.avail_in = ilen;
125 state->ostream.next_out = out;
126 state->ostream.avail_out = olen;
127 if (ilen > 0)
128 err = deflate(&state->ostream, Z_SYNC_FLUSH);
129 if (err != Z_OK)
130 return -1;
132 #ifdef DEBUG_ZLIB
133 fprintf(stderr, "compress(%4d)->%4d %s\n",
134 ilen, olen - state->ostream.avail_out,
135 (ilen != olen - state->ostream.avail_out)?"zlib":"clear");
136 #endif
138 return olen - state->ostream.avail_out;
141 static int
142 zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
143 unsigned int olen, unsigned char *in, unsigned int ilen)
145 int err = Z_OK;
147 struct zlib_state *state =
148 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
149 zlib_stateful_ex_idx);
151 if (state == NULL)
152 return 0;
154 state->istream.next_in = in;
155 state->istream.avail_in = ilen;
156 state->istream.next_out = out;
157 state->istream.avail_out = olen;
158 if (ilen > 0)
159 err = inflate(&state->istream, Z_SYNC_FLUSH);
160 if (err != Z_OK)
161 return -1;
163 #ifdef DEBUG_ZLIB
164 fprintf(stderr, "expand(%4d)->%4d %s\n",
165 ilen, olen - state->istream.avail_out,
166 (ilen != olen - state->istream.avail_out)?"zlib":"clear");
167 #endif
169 return olen - state->istream.avail_out;
172 #endif
174 COMP_METHOD *
175 COMP_zlib(void)
177 COMP_METHOD *meth = &zlib_method_nozlib;
179 #ifdef ZLIB
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)
192 goto err;
194 if (!OPENSSL_init_crypto(0, NULL))
195 goto err;
197 meth = &zlib_stateful_method;
200 err:
201 #endif
203 return (meth);
206 void
207 COMP_zlib_cleanup(void)
211 #ifdef ZLIB
213 /* Zlib based compression/decompression filter BIO */
215 typedef struct {
216 unsigned char *ibuf; /* Input buffer */
217 int ibufsize; /* Buffer size */
218 z_stream zin; /* Input decompress context */
219 unsigned char *obuf; /* Output buffer */
220 int obufsize; /* Output buffer size */
221 unsigned char *optr; /* Position in output buffer */
222 int ocount; /* Amount of data in output buffer */
223 int odone; /* deflate EOF */
224 int comp_level; /* Compression level to use */
225 z_stream zout; /* Output compression context */
226 } BIO_ZLIB_CTX;
228 #define ZLIB_DEFAULT_BUFSIZE 1024
230 static int bio_zlib_new(BIO *bi);
231 static int bio_zlib_free(BIO *bi);
232 static int bio_zlib_read(BIO *b, char *out, int outl);
233 static int bio_zlib_write(BIO *b, const char *in, int inl);
234 static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr);
235 static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp);
237 static BIO_METHOD bio_meth_zlib = {
238 .type = BIO_TYPE_COMP,
239 .name = "zlib",
240 .bwrite = bio_zlib_write,
241 .bread = bio_zlib_read,
242 .ctrl = bio_zlib_ctrl,
243 .create = bio_zlib_new,
244 .destroy = bio_zlib_free,
245 .callback_ctrl = bio_zlib_callback_ctrl
248 BIO_METHOD *
249 BIO_f_zlib(void)
251 return &bio_meth_zlib;
255 static int
256 bio_zlib_new(BIO *bi)
258 BIO_ZLIB_CTX *ctx;
260 ctx = malloc(sizeof(BIO_ZLIB_CTX));
261 if (!ctx) {
262 COMPerror(ERR_R_MALLOC_FAILURE);
263 return 0;
265 ctx->ibuf = NULL;
266 ctx->obuf = NULL;
267 ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE;
268 ctx->obufsize = ZLIB_DEFAULT_BUFSIZE;
269 ctx->zin.zalloc = Z_NULL;
270 ctx->zin.zfree = Z_NULL;
271 ctx->zin.next_in = NULL;
272 ctx->zin.avail_in = 0;
273 ctx->zin.next_out = NULL;
274 ctx->zin.avail_out = 0;
275 ctx->zout.zalloc = Z_NULL;
276 ctx->zout.zfree = Z_NULL;
277 ctx->zout.next_in = NULL;
278 ctx->zout.avail_in = 0;
279 ctx->zout.next_out = NULL;
280 ctx->zout.avail_out = 0;
281 ctx->odone = 0;
282 ctx->comp_level = Z_DEFAULT_COMPRESSION;
283 bi->init = 1;
284 bi->ptr = (char *)ctx;
285 bi->flags = 0;
286 return 1;
289 static int
290 bio_zlib_free(BIO *bi)
292 BIO_ZLIB_CTX *ctx;
294 if (!bi)
295 return 0;
296 ctx = (BIO_ZLIB_CTX *)bi->ptr;
297 if (ctx->ibuf) {
298 /* Destroy decompress context */
299 inflateEnd(&ctx->zin);
300 free(ctx->ibuf);
302 if (ctx->obuf) {
303 /* Destroy compress context */
304 deflateEnd(&ctx->zout);
305 free(ctx->obuf);
307 free(ctx);
308 bi->ptr = NULL;
309 bi->init = 0;
310 bi->flags = 0;
311 return 1;
314 static int
315 bio_zlib_read(BIO *b, char *out, int outl)
317 BIO_ZLIB_CTX *ctx;
318 int ret;
319 z_stream *zin;
321 if (!out || !outl)
322 return 0;
323 ctx = (BIO_ZLIB_CTX *)b->ptr;
324 zin = &ctx->zin;
325 BIO_clear_retry_flags(b);
326 if (!ctx->ibuf) {
327 ctx->ibuf = malloc(ctx->ibufsize);
328 if (!ctx->ibuf) {
329 COMPerror(ERR_R_MALLOC_FAILURE);
330 return 0;
332 inflateInit(zin);
333 zin->next_in = ctx->ibuf;
334 zin->avail_in = 0;
337 /* Copy output data directly to supplied buffer */
338 zin->next_out = (unsigned char *)out;
339 zin->avail_out = (unsigned int)outl;
340 for (;;) {
341 /* Decompress while data available */
342 while (zin->avail_in) {
343 ret = inflate(zin, 0);
344 if ((ret != Z_OK) && (ret != Z_STREAM_END)) {
345 COMPerror(COMP_R_ZLIB_INFLATE_ERROR);
346 ERR_asprintf_error_data("zlib error:%s",
347 zError(ret));
348 return 0;
350 /* If EOF or we've read everything then return */
351 if ((ret == Z_STREAM_END) || !zin->avail_out)
352 return outl - zin->avail_out;
355 /* No data in input buffer try to read some in,
356 * if an error then return the total data read.
358 ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize);
359 if (ret <= 0) {
360 /* Total data read */
361 int tot = outl - zin->avail_out;
362 BIO_copy_next_retry(b);
363 if (ret < 0)
364 return (tot > 0) ? tot : ret;
365 return tot;
367 zin->avail_in = ret;
368 zin->next_in = ctx->ibuf;
372 static int
373 bio_zlib_write(BIO *b, const char *in, int inl)
375 BIO_ZLIB_CTX *ctx;
376 int ret;
377 z_stream *zout;
379 if (!in || !inl)
380 return 0;
381 ctx = (BIO_ZLIB_CTX *)b->ptr;
382 if (ctx->odone)
383 return 0;
384 zout = &ctx->zout;
385 BIO_clear_retry_flags(b);
386 if (!ctx->obuf) {
387 ctx->obuf = malloc(ctx->obufsize);
388 /* Need error here */
389 if (!ctx->obuf) {
390 COMPerror(ERR_R_MALLOC_FAILURE);
391 return 0;
393 ctx->optr = ctx->obuf;
394 ctx->ocount = 0;
395 deflateInit(zout, ctx->comp_level);
396 zout->next_out = ctx->obuf;
397 zout->avail_out = ctx->obufsize;
399 /* Obtain input data directly from supplied buffer */
400 zout->next_in = (void *)in;
401 zout->avail_in = inl;
402 for (;;) {
403 /* If data in output buffer write it first */
404 while (ctx->ocount) {
405 ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
406 if (ret <= 0) {
407 /* Total data written */
408 int tot = inl - zout->avail_in;
409 BIO_copy_next_retry(b);
410 if (ret < 0)
411 return (tot > 0) ? tot : ret;
412 return tot;
414 ctx->optr += ret;
415 ctx->ocount -= ret;
418 /* Have we consumed all supplied data? */
419 if (!zout->avail_in)
420 return inl;
422 /* Compress some more */
424 /* Reset buffer */
425 ctx->optr = ctx->obuf;
426 zout->next_out = ctx->obuf;
427 zout->avail_out = ctx->obufsize;
428 /* Compress some more */
429 ret = deflate(zout, 0);
430 if (ret != Z_OK) {
431 COMPerror(COMP_R_ZLIB_DEFLATE_ERROR);
432 ERR_asprintf_error_data("zlib error:%s", zError(ret));
433 return 0;
435 ctx->ocount = ctx->obufsize - zout->avail_out;
439 static int
440 bio_zlib_flush(BIO *b)
442 BIO_ZLIB_CTX *ctx;
443 int ret;
444 z_stream *zout;
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))
449 return 1;
450 zout = &ctx->zout;
451 BIO_clear_retry_flags(b);
452 /* No more input data */
453 zout->next_in = NULL;
454 zout->avail_in = 0;
455 for (;;) {
456 /* If data in output buffer write it first */
457 while (ctx->ocount) {
458 ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
459 if (ret <= 0) {
460 BIO_copy_next_retry(b);
461 return ret;
463 ctx->optr += ret;
464 ctx->ocount -= ret;
466 if (ctx->odone)
467 return 1;
469 /* Compress some more */
471 /* Reset buffer */
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)
478 ctx->odone = 1;
479 else if (ret != Z_OK) {
480 COMPerror(COMP_R_ZLIB_DEFLATE_ERROR);
481 ERR_asprintf_error_data("zlib error:%s", zError(ret));
482 return 0;
484 ctx->ocount = ctx->obufsize - zout->avail_out;
488 static long
489 bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
491 BIO_ZLIB_CTX *ctx;
492 int ret, *ip;
493 int ibs, obs;
494 if (!b->next_bio)
495 return 0;
496 ctx = (BIO_ZLIB_CTX *)b->ptr;
497 switch (cmd) {
499 case BIO_CTRL_RESET:
500 ctx->ocount = 0;
501 ctx->odone = 0;
502 ret = 1;
503 break;
505 case BIO_CTRL_FLUSH:
506 ret = bio_zlib_flush(b);
507 if (ret > 0)
508 ret = BIO_flush(b->next_bio);
509 break;
511 case BIO_C_SET_BUFF_SIZE:
512 ibs = -1;
513 obs = -1;
514 if (ptr != NULL) {
515 ip = ptr;
516 if (*ip == 0)
517 ibs = (int) num;
518 else
519 obs = (int) num;
520 } else {
521 ibs = (int)num;
522 obs = ibs;
525 if (ibs != -1) {
526 free(ctx->ibuf);
527 ctx->ibuf = NULL;
528 ctx->ibufsize = ibs;
531 if (obs != -1) {
532 free(ctx->obuf);
533 ctx->obuf = NULL;
534 ctx->obufsize = obs;
536 ret = 1;
537 break;
539 case BIO_C_DO_STATE_MACHINE:
540 BIO_clear_retry_flags(b);
541 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
542 BIO_copy_next_retry(b);
543 break;
545 default:
546 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
547 break;
551 return ret;
555 static long
556 bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
558 if (!b->next_bio)
559 return 0;
560 return BIO_callback_ctrl(b->next_bio, cmd, fp);
563 #endif