GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/crypto/../../libssl/src/crypto/comp/c_zlib.c Lines: 0 2 0.0 %
Date: 2016-12-06 Branches: 0 0 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: c_zlib.c,v 1.18 2015/12/23 20:37:23 mmcc 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
9
COMP_METHOD *COMP_zlib(void );
10
11
static COMP_METHOD zlib_method_nozlib = {
12
	.type = NID_undef,
13
	.name = "(undef)"
14
};
15
16
#ifdef ZLIB
17
18
#include <zlib.h>
19
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);
26
27
28
/* memory allocations functions for zlib intialization */
29
static void*
30
zlib_zalloc(void* opaque, unsigned int no, unsigned int size)
31
{
32
	return calloc(no, size);
33
}
34
35
static void
36
zlib_zfree(void* opaque, void* address)
37
{
38
	free(address);
39
}
40
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
48
};
49
50
struct zlib_state {
51
	z_stream istream;
52
	z_stream ostream;
53
};
54
55
static int zlib_stateful_ex_idx = -1;
56
57
static int
58
zlib_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
93
err:
94
	free(state);
95
	return 0;
96
}
97
98
static void
99
zlib_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
111
static int
112
zlib_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
141
static int
142
zlib_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
174
COMP_METHOD *
175
COMP_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
195
		meth = &zlib_stateful_method;
196
	}
197
198
err:
199
#endif
200
201
	return (meth);
202
}
203
204
void
205
COMP_zlib_cleanup(void)
206
{
207
}
208
209
#ifdef ZLIB
210
211
/* Zlib based compression/decompression filter BIO */
212
213
typedef struct {
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 */
224
} BIO_ZLIB_CTX;
225
226
#define ZLIB_DEFAULT_BUFSIZE 1024
227
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);
234
235
static BIO_METHOD bio_meth_zlib = {
236
	.type = BIO_TYPE_COMP,
237
	.name = "zlib",
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
244
};
245
246
BIO_METHOD *
247
BIO_f_zlib(void)
248
{
249
	return &bio_meth_zlib;
250
}
251
252
253
static int
254
bio_zlib_new(BIO *bi)
255
{
256
	BIO_ZLIB_CTX *ctx;
257
258
	ctx = malloc(sizeof(BIO_ZLIB_CTX));
259
	if (!ctx) {
260
		COMPerr(COMP_F_BIO_ZLIB_NEW, ERR_R_MALLOC_FAILURE);
261
		return 0;
262
	}
263
	ctx->ibuf = NULL;
264
	ctx->obuf = NULL;
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;
279
	ctx->odone = 0;
280
	ctx->comp_level = Z_DEFAULT_COMPRESSION;
281
	bi->init = 1;
282
	bi->ptr = (char *)ctx;
283
	bi->flags = 0;
284
	return 1;
285
}
286
287
static int
288
bio_zlib_free(BIO *bi)
289
{
290
	BIO_ZLIB_CTX *ctx;
291
292
	if (!bi)
293
		return 0;
294
	ctx = (BIO_ZLIB_CTX *)bi->ptr;
295
	if (ctx->ibuf) {
296
		/* Destroy decompress context */
297
		inflateEnd(&ctx->zin);
298
		free(ctx->ibuf);
299
	}
300
	if (ctx->obuf) {
301
		/* Destroy compress context */
302
		deflateEnd(&ctx->zout);
303
		free(ctx->obuf);
304
	}
305
	free(ctx);
306
	bi->ptr = NULL;
307
	bi->init = 0;
308
	bi->flags = 0;
309
	return 1;
310
}
311
312
static int
313
bio_zlib_read(BIO *b, char *out, int outl)
314
{
315
	BIO_ZLIB_CTX *ctx;
316
	int ret;
317
	z_stream *zin;
318
319
	if (!out || !outl)
320
		return 0;
321
	ctx = (BIO_ZLIB_CTX *)b->ptr;
322
	zin = &ctx->zin;
323
	BIO_clear_retry_flags(b);
324
	if (!ctx->ibuf) {
325
		ctx->ibuf = malloc(ctx->ibufsize);
326
		if (!ctx->ibuf) {
327
			COMPerr(COMP_F_BIO_ZLIB_READ, ERR_R_MALLOC_FAILURE);
328
			return 0;
329
		}
330
		inflateInit(zin);
331
		zin->next_in = ctx->ibuf;
332
		zin->avail_in = 0;
333
	}
334
335
	/* Copy output data directly to supplied buffer */
336
	zin->next_out = (unsigned char *)out;
337
	zin->avail_out = (unsigned int)outl;
338
	for (;;) {
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",
346
				    zError(ret));
347
				return 0;
348
			}
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;
352
		}
353
354
		/* No data in input buffer try to read some in,
355
		 * if an error then return the total data read.
356
		 */
357
		ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize);
358
		if (ret <= 0) {
359
			/* Total data read */
360
			int tot = outl - zin->avail_out;
361
			BIO_copy_next_retry(b);
362
			if (ret < 0)
363
				return (tot > 0) ? tot : ret;
364
			return tot;
365
		}
366
		zin->avail_in = ret;
367
		zin->next_in = ctx->ibuf;
368
	}
369
}
370
371
static int
372
bio_zlib_write(BIO *b, const char *in, int inl)
373
{
374
	BIO_ZLIB_CTX *ctx;
375
	int ret;
376
	z_stream *zout;
377
378
	if (!in || !inl)
379
		return 0;
380
	ctx = (BIO_ZLIB_CTX *)b->ptr;
381
	if (ctx->odone)
382
		return 0;
383
	zout = &ctx->zout;
384
	BIO_clear_retry_flags(b);
385
	if (!ctx->obuf) {
386
		ctx->obuf = malloc(ctx->obufsize);
387
		/* Need error here */
388
		if (!ctx->obuf) {
389
			COMPerr(COMP_F_BIO_ZLIB_WRITE, ERR_R_MALLOC_FAILURE);
390
			return 0;
391
		}
392
		ctx->optr = ctx->obuf;
393
		ctx->ocount = 0;
394
		deflateInit(zout, ctx->comp_level);
395
		zout->next_out = ctx->obuf;
396
		zout->avail_out = ctx->obufsize;
397
	}
398
	/* Obtain input data directly from supplied buffer */
399
	zout->next_in = (void *)in;
400
	zout->avail_in = inl;
401
	for (;;) {
402
		/* If data in output buffer write it first */
403
		while (ctx->ocount) {
404
			ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
405
			if (ret <= 0) {
406
				/* Total data written */
407
				int tot = inl - zout->avail_in;
408
				BIO_copy_next_retry(b);
409
				if (ret < 0)
410
					return (tot > 0) ? tot : ret;
411
				return tot;
412
			}
413
			ctx->optr += ret;
414
			ctx->ocount -= ret;
415
		}
416
417
		/* Have we consumed all supplied data? */
418
		if (!zout->avail_in)
419
			return inl;
420
421
		/* Compress some more */
422
423
		/* Reset buffer */
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);
429
		if (ret != Z_OK) {
430
			COMPerr(COMP_F_BIO_ZLIB_WRITE,
431
			    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
439
static int
440
bio_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
			COMPerr(COMP_F_BIO_ZLIB_FLUSH,
481
			    COMP_R_ZLIB_DEFLATE_ERROR);
482
			ERR_asprintf_error_data("zlib error:%s", zError(ret));
483
			return 0;
484
		}
485
		ctx->ocount = ctx->obufsize - zout->avail_out;
486
	}
487
}
488
489
static long
490
bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
491
{
492
	BIO_ZLIB_CTX *ctx;
493
	int ret, *ip;
494
	int ibs, obs;
495
	if (!b->next_bio)
496
		return 0;
497
	ctx = (BIO_ZLIB_CTX *)b->ptr;
498
	switch (cmd) {
499
500
	case BIO_CTRL_RESET:
501
		ctx->ocount = 0;
502
		ctx->odone = 0;
503
		ret = 1;
504
		break;
505
506
	case BIO_CTRL_FLUSH:
507
		ret = bio_zlib_flush(b);
508
		if (ret > 0)
509
			ret = BIO_flush(b->next_bio);
510
		break;
511
512
	case BIO_C_SET_BUFF_SIZE:
513
		ibs = -1;
514
		obs = -1;
515
		if (ptr != NULL) {
516
			ip = ptr;
517
			if (*ip == 0)
518
				ibs = (int) num;
519
			else
520
				obs = (int) num;
521
		} else {
522
			ibs = (int)num;
523
			obs = ibs;
524
		}
525
526
		if (ibs != -1) {
527
			free(ctx->ibuf);
528
			ctx->ibuf = NULL;
529
			ctx->ibufsize = ibs;
530
		}
531
532
		if (obs != -1) {
533
			free(ctx->obuf);
534
			ctx->obuf = NULL;
535
			ctx->obufsize = obs;
536
		}
537
		ret = 1;
538
		break;
539
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);
544
		break;
545
546
	default:
547
		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
548
		break;
549
550
	}
551
552
	return ret;
553
}
554
555
556
static long
557
bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
558
{
559
	if (!b->next_bio)
560
		return 0;
561
	return BIO_callback_ctrl(b->next_bio, cmd, fp);
562
}
563
564
#endif