GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/comp/c_zlib.c Lines: 0 1 0.0 %
Date: 2017-11-13 Branches: 0 0 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: c_zlib.c,v 1.19 2017/01/29 17:49:22 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
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
		COMPerror(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
			COMPerror(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
				COMPerror(COMP_R_ZLIB_INFLATE_ERROR);
344
				ERR_asprintf_error_data("zlib error:%s",
345
				    zError(ret));
346
				return 0;
347
			}
348
			/* If EOF or we've read everything then return */
349
			if ((ret == Z_STREAM_END) || !zin->avail_out)
350
				return outl - zin->avail_out;
351
		}
352
353
		/* No data in input buffer try to read some in,
354
		 * if an error then return the total data read.
355
		 */
356
		ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize);
357
		if (ret <= 0) {
358
			/* Total data read */
359
			int tot = outl - zin->avail_out;
360
			BIO_copy_next_retry(b);
361
			if (ret < 0)
362
				return (tot > 0) ? tot : ret;
363
			return tot;
364
		}
365
		zin->avail_in = ret;
366
		zin->next_in = ctx->ibuf;
367
	}
368
}
369
370
static int
371
bio_zlib_write(BIO *b, const char *in, int inl)
372
{
373
	BIO_ZLIB_CTX *ctx;
374
	int ret;
375
	z_stream *zout;
376
377
	if (!in || !inl)
378
		return 0;
379
	ctx = (BIO_ZLIB_CTX *)b->ptr;
380
	if (ctx->odone)
381
		return 0;
382
	zout = &ctx->zout;
383
	BIO_clear_retry_flags(b);
384
	if (!ctx->obuf) {
385
		ctx->obuf = malloc(ctx->obufsize);
386
		/* Need error here */
387
		if (!ctx->obuf) {
388
			COMPerror(ERR_R_MALLOC_FAILURE);
389
			return 0;
390
		}
391
		ctx->optr = ctx->obuf;
392
		ctx->ocount = 0;
393
		deflateInit(zout, ctx->comp_level);
394
		zout->next_out = ctx->obuf;
395
		zout->avail_out = ctx->obufsize;
396
	}
397
	/* Obtain input data directly from supplied buffer */
398
	zout->next_in = (void *)in;
399
	zout->avail_in = inl;
400
	for (;;) {
401
		/* If data in output buffer write it first */
402
		while (ctx->ocount) {
403
			ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
404
			if (ret <= 0) {
405
				/* Total data written */
406
				int tot = inl - zout->avail_in;
407
				BIO_copy_next_retry(b);
408
				if (ret < 0)
409
					return (tot > 0) ? tot : ret;
410
				return tot;
411
			}
412
			ctx->optr += ret;
413
			ctx->ocount -= ret;
414
		}
415
416
		/* Have we consumed all supplied data? */
417
		if (!zout->avail_in)
418
			return inl;
419
420
		/* Compress some more */
421
422
		/* Reset buffer */
423
		ctx->optr = ctx->obuf;
424
		zout->next_out = ctx->obuf;
425
		zout->avail_out = ctx->obufsize;
426
		/* Compress some more */
427
		ret = deflate(zout, 0);
428
		if (ret != Z_OK) {
429
			COMPerror(COMP_R_ZLIB_DEFLATE_ERROR);
430
			ERR_asprintf_error_data("zlib error:%s", zError(ret));
431
			return 0;
432
		}
433
		ctx->ocount = ctx->obufsize - zout->avail_out;
434
	}
435
}
436
437
static int
438
bio_zlib_flush(BIO *b)
439
{
440
	BIO_ZLIB_CTX *ctx;
441
	int ret;
442
	z_stream *zout;
443
444
	ctx = (BIO_ZLIB_CTX *)b->ptr;
445
	/* If no data written or already flush show success */
446
	if (!ctx->obuf || (ctx->odone && !ctx->ocount))
447
		return 1;
448
	zout = &ctx->zout;
449
	BIO_clear_retry_flags(b);
450
	/* No more input data */
451
	zout->next_in = NULL;
452
	zout->avail_in = 0;
453
	for (;;) {
454
		/* If data in output buffer write it first */
455
		while (ctx->ocount) {
456
			ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
457
			if (ret <= 0) {
458
				BIO_copy_next_retry(b);
459
				return ret;
460
			}
461
			ctx->optr += ret;
462
			ctx->ocount -= ret;
463
		}
464
		if (ctx->odone)
465
			return 1;
466
467
		/* Compress some more */
468
469
		/* Reset buffer */
470
		ctx->optr = ctx->obuf;
471
		zout->next_out = ctx->obuf;
472
		zout->avail_out = ctx->obufsize;
473
		/* Compress some more */
474
		ret = deflate(zout, Z_FINISH);
475
		if (ret == Z_STREAM_END)
476
			ctx->odone = 1;
477
		else if (ret != Z_OK) {
478
			COMPerror(COMP_R_ZLIB_DEFLATE_ERROR);
479
			ERR_asprintf_error_data("zlib error:%s", zError(ret));
480
			return 0;
481
		}
482
		ctx->ocount = ctx->obufsize - zout->avail_out;
483
	}
484
}
485
486
static long
487
bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
488
{
489
	BIO_ZLIB_CTX *ctx;
490
	int ret, *ip;
491
	int ibs, obs;
492
	if (!b->next_bio)
493
		return 0;
494
	ctx = (BIO_ZLIB_CTX *)b->ptr;
495
	switch (cmd) {
496
497
	case BIO_CTRL_RESET:
498
		ctx->ocount = 0;
499
		ctx->odone = 0;
500
		ret = 1;
501
		break;
502
503
	case BIO_CTRL_FLUSH:
504
		ret = bio_zlib_flush(b);
505
		if (ret > 0)
506
			ret = BIO_flush(b->next_bio);
507
		break;
508
509
	case BIO_C_SET_BUFF_SIZE:
510
		ibs = -1;
511
		obs = -1;
512
		if (ptr != NULL) {
513
			ip = ptr;
514
			if (*ip == 0)
515
				ibs = (int) num;
516
			else
517
				obs = (int) num;
518
		} else {
519
			ibs = (int)num;
520
			obs = ibs;
521
		}
522
523
		if (ibs != -1) {
524
			free(ctx->ibuf);
525
			ctx->ibuf = NULL;
526
			ctx->ibufsize = ibs;
527
		}
528
529
		if (obs != -1) {
530
			free(ctx->obuf);
531
			ctx->obuf = NULL;
532
			ctx->obufsize = obs;
533
		}
534
		ret = 1;
535
		break;
536
537
	case BIO_C_DO_STATE_MACHINE:
538
		BIO_clear_retry_flags(b);
539
		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
540
		BIO_copy_next_retry(b);
541
		break;
542
543
	default:
544
		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
545
		break;
546
547
	}
548
549
	return ret;
550
}
551
552
553
static long
554
bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
555
{
556
	if (!b->next_bio)
557
		return 0;
558
	return BIO_callback_ctrl(b->next_bio, cmd, fp);
559
}
560
561
#endif