OpenCoverage

c_zlib.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/libressl/src/crypto/comp/c_zlib.c
Source codeSwitch to Preprocessed file
LineSourceCount
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>-
8-
9COMP_METHOD *COMP_zlib(void );-
10-
11static COMP_METHOD zlib_method_nozlib = {-
12 .type = NID_undef,-
13 .name = "(undef)"-
14};-
15-
16#ifdef ZLIB-
17-
18#include <zlib.h>-
19-
20static int zlib_stateful_init(COMP_CTX *ctx);-
21static void zlib_stateful_finish(COMP_CTX *ctx);-
22static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,-
23 unsigned int olen, unsigned char *in, unsigned int ilen);-
24static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,-
25 unsigned int olen, unsigned char *in, unsigned int ilen);-
26-
27-
28/* memory allocations functions for zlib intialization */-
29static void*-
30zlib_zalloc(void* opaque, unsigned int no, unsigned int size)-
31{-
32 return calloc(no, size);-
33}-
34-
35static void-
36zlib_zfree(void* opaque, void* address)-
37{-
38 free(address);-
39}-
40-
41static 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-
48};-
49-
50struct zlib_state {-
51 z_stream istream;-
52 z_stream ostream;-
53};-
54-
55static int zlib_stateful_ex_idx = -1;-
56-
57static int-
58zlib_stateful_init(COMP_CTX *ctx)-
59{-
60 int err;-
61 struct zlib_state *state = malloc(sizeof(struct zlib_state));-
62-
63 if (state == NULL)-
64 goto err;-
65-
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;-
76-
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;-
88-
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;-
92-
93err:-
94 free(state);-
95 return 0;-
96}-
97-
98static void-
99zlib_stateful_finish(COMP_CTX *ctx)-
100{-
101 struct zlib_state *state =-
102 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,-
103 zlib_stateful_ex_idx);-
104-
105 inflateEnd(&state->istream);-
106 deflateEnd(&state->ostream);-
107 free(state);-
108 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data);-
109}-
110-
111static int-
112zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,-
113 unsigned int olen, unsigned char *in, unsigned int ilen)-
114{-
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);-
119-
120 if (state == NULL)-
121 return -1;-
122-
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;-
131-
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-
137-
138 return olen - state->ostream.avail_out;-
139}-
140-
141static int-
142zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,-
143 unsigned int olen, unsigned char *in, unsigned int ilen)-
144{-
145 int err = Z_OK;-
146-
147 struct zlib_state *state =-
148 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,-
149 zlib_stateful_ex_idx);-
150-
151 if (state == NULL)-
152 return 0;-
153-
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;-
162-
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-
168-
169 return olen - state->istream.avail_out;-
170}-
171-
172#endif-
173-
174COMP_METHOD *-
175COMP_zlib(void)-
176{-
177 COMP_METHOD *meth = &zlib_method_nozlib;-
178-
179#ifdef ZLIB-
180 {-
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;-
193 }-
194 if (!OPENSSL_init_crypto(0, NULL))-
195 goto err;-
196-
197 meth = &zlib_stateful_method;-
198 }-
199-
200err:-
201#endif-
202-
203 return (meth);
never executed: return (meth);
0
204}-
205-
206void-
207COMP_zlib_cleanup(void)-
208{-
209}-
210-
211#ifdef ZLIB-
212-
213/* Zlib based compression/decompression filter BIO */-
214-
215typedef 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;-
227-
228#define ZLIB_DEFAULT_BUFSIZE 1024-
229-
230static int bio_zlib_new(BIO *bi);-
231static int bio_zlib_free(BIO *bi);-
232static int bio_zlib_read(BIO *b, char *out, int outl);-
233static int bio_zlib_write(BIO *b, const char *in, int inl);-
234static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr);-
235static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp);-
236-
237static 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-
246};-
247-
248BIO_METHOD *-
249BIO_f_zlib(void)-
250{-
251 return &bio_meth_zlib;-
252}-
253-
254-
255static int-
256bio_zlib_new(BIO *bi)-
257{-
258 BIO_ZLIB_CTX *ctx;-
259-
260 ctx = malloc(sizeof(BIO_ZLIB_CTX));-
261 if (!ctx) {-
262 COMPerror(ERR_R_MALLOC_FAILURE);-
263 return 0;-
264 }-
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;-
287}-
288-
289static int-
290bio_zlib_free(BIO *bi)-
291{-
292 BIO_ZLIB_CTX *ctx;-
293-
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);-
301 }-
302 if (ctx->obuf) {-
303 /* Destroy compress context */-
304 deflateEnd(&ctx->zout);-
305 free(ctx->obuf);-
306 }-
307 free(ctx);-
308 bi->ptr = NULL;-
309 bi->init = 0;-
310 bi->flags = 0;-
311 return 1;-
312}-
313-
314static int-
315bio_zlib_read(BIO *b, char *out, int outl)-
316{-
317 BIO_ZLIB_CTX *ctx;-
318 int ret;-
319 z_stream *zin;-
320-
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;-
331 }-
332 inflateInit(zin);-
333 zin->next_in = ctx->ibuf;-
334 zin->avail_in = 0;-
335 }-
336-
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;-
349 }-
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;-
353 }-
354-
355 /* No data in input buffer try to read some in,-
356 * if an error then return the total data read.-
357 */-
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;-
366 }-
367 zin->avail_in = ret;-
368 zin->next_in = ctx->ibuf;-
369 }-
370}-
371-
372static int-
373bio_zlib_write(BIO *b, const char *in, int inl)-
374{-
375 BIO_ZLIB_CTX *ctx;-
376 int ret;-
377 z_stream *zout;-
378-
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;-
392 }-
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;-
398 }-
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;-
413 }-
414 ctx->optr += ret;-
415 ctx->ocount -= ret;-
416 }-
417-
418 /* Have we consumed all supplied data? */-
419 if (!zout->avail_in)-
420 return inl;-
421-
422 /* Compress some more */-
423-
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;-
434 }-
435 ctx->ocount = ctx->obufsize - zout->avail_out;-
436 }-
437}-
438-
439static int-
440bio_zlib_flush(BIO *b)-
441{-
442 BIO_ZLIB_CTX *ctx;-
443 int ret;-
444 z_stream *zout;-
445-
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;-
462 }-
463 ctx->optr += ret;-
464 ctx->ocount -= ret;-
465 }-
466 if (ctx->odone)-
467 return 1;-
468-
469 /* Compress some more */-
470-
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;-
483 }-
484 ctx->ocount = ctx->obufsize - zout->avail_out;-
485 }-
486}-
487-
488static long-
489bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)-
490{-
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) {-
498-
499 case BIO_CTRL_RESET:-
500 ctx->ocount = 0;-
501 ctx->odone = 0;-
502 ret = 1;-
503 break;-
504-
505 case BIO_CTRL_FLUSH:-
506 ret = bio_zlib_flush(b);-
507 if (ret > 0)-
508 ret = BIO_flush(b->next_bio);-
509 break;-
510-
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;-
523 }-
524-
525 if (ibs != -1) {-
526 free(ctx->ibuf);-
527 ctx->ibuf = NULL;-
528 ctx->ibufsize = ibs;-
529 }-
530-
531 if (obs != -1) {-
532 free(ctx->obuf);-
533 ctx->obuf = NULL;-
534 ctx->obufsize = obs;-
535 }-
536 ret = 1;-
537 break;-
538-
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;-
544-
545 default:-
546 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);-
547 break;-
548-
549 }-
550-
551 return ret;-
552}-
553-
554-
555static long-
556bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)-
557{-
558 if (!b->next_bio)-
559 return 0;-
560 return BIO_callback_ctrl(b->next_bio, cmd, fp);-
561}-
562-
563#endif-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.2.2