GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/bio/bf_buff.c Lines: 129 260 49.6 %
Date: 2017-11-07 Branches: 50 151 33.1 %

Line Branch Exec Source
1
/* $OpenBSD: bf_buff.c,v 1.24 2017/01/29 17:49:22 beck Exp $ */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3
 * All rights reserved.
4
 *
5
 * This package is an SSL implementation written
6
 * by Eric Young (eay@cryptsoft.com).
7
 * The implementation was written so as to conform with Netscapes SSL.
8
 *
9
 * This library is free for commercial and non-commercial use as long as
10
 * the following conditions are aheared to.  The following conditions
11
 * apply to all code found in this distribution, be it the RC4, RSA,
12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13
 * included with this distribution is covered by the same copyright terms
14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15
 *
16
 * Copyright remains Eric Young's, and as such any Copyright notices in
17
 * the code are not to be removed.
18
 * If this package is used in a product, Eric Young should be given attribution
19
 * as the author of the parts of the library used.
20
 * This can be in the form of a textual message at program startup or
21
 * in documentation (online or textual) provided with the package.
22
 *
23
 * Redistribution and use in source and binary forms, with or without
24
 * modification, are permitted provided that the following conditions
25
 * are met:
26
 * 1. Redistributions of source code must retain the copyright
27
 *    notice, this list of conditions and the following disclaimer.
28
 * 2. Redistributions in binary form must reproduce the above copyright
29
 *    notice, this list of conditions and the following disclaimer in the
30
 *    documentation and/or other materials provided with the distribution.
31
 * 3. All advertising materials mentioning features or use of this software
32
 *    must display the following acknowledgement:
33
 *    "This product includes cryptographic software written by
34
 *     Eric Young (eay@cryptsoft.com)"
35
 *    The word 'cryptographic' can be left out if the rouines from the library
36
 *    being used are not cryptographic related :-).
37
 * 4. If you include any Windows specific code (or a derivative thereof) from
38
 *    the apps directory (application code) you must include an acknowledgement:
39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40
 *
41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51
 * SUCH DAMAGE.
52
 *
53
 * The licence and distribution terms for any publically available version or
54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55
 * copied and put under another distribution licence
56
 * [including the GNU Public Licence.]
57
 */
58
59
#include <errno.h>
60
#include <stdio.h>
61
#include <string.h>
62
63
#include <openssl/bio.h>
64
#include <openssl/err.h>
65
66
static int buffer_write(BIO *h, const char *buf, int num);
67
static int buffer_read(BIO *h, char *buf, int size);
68
static int buffer_puts(BIO *h, const char *str);
69
static int buffer_gets(BIO *h, char *str, int size);
70
static long buffer_ctrl(BIO *h, int cmd, long arg1, void *arg2);
71
static int buffer_new(BIO *h);
72
static int buffer_free(BIO *data);
73
static long buffer_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
74
#define DEFAULT_BUFFER_SIZE	4096
75
76
static BIO_METHOD methods_buffer = {
77
	.type = BIO_TYPE_BUFFER,
78
	.name = "buffer",
79
	.bwrite = buffer_write,
80
	.bread = buffer_read,
81
	.bputs = buffer_puts,
82
	.bgets = buffer_gets,
83
	.ctrl = buffer_ctrl,
84
	.create = buffer_new,
85
	.destroy = buffer_free,
86
	.callback_ctrl = buffer_callback_ctrl
87
};
88
89
BIO_METHOD *
90
BIO_f_buffer(void)
91
{
92
17014
	return (&methods_buffer);
93
}
94
95
static int
96
buffer_new(BIO *bi)
97
{
98
	BIO_F_BUFFER_CTX *ctx;
99
100
17018
	ctx = malloc(sizeof(BIO_F_BUFFER_CTX));
101
8509
	if (ctx == NULL)
102
		return (0);
103
8509
	ctx->ibuf = malloc(DEFAULT_BUFFER_SIZE);
104
8509
	if (ctx->ibuf == NULL) {
105
		free(ctx);
106
		return (0);
107
	}
108
8509
	ctx->obuf = malloc(DEFAULT_BUFFER_SIZE);
109
8509
	if (ctx->obuf == NULL) {
110
		free(ctx->ibuf);
111
		free(ctx);
112
		return (0);
113
	}
114
8509
	ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
115
8509
	ctx->obuf_size = DEFAULT_BUFFER_SIZE;
116
8509
	ctx->ibuf_len = 0;
117
8509
	ctx->ibuf_off = 0;
118
8509
	ctx->obuf_len = 0;
119
8509
	ctx->obuf_off = 0;
120
121
8509
	bi->init = 1;
122
8509
	bi->ptr = (char *)ctx;
123
8509
	bi->flags = 0;
124
8509
	return (1);
125
8509
}
126
127
static int
128
buffer_free(BIO *a)
129
{
130
	BIO_F_BUFFER_CTX *b;
131
132
17018
	if (a == NULL)
133
		return (0);
134
8509
	b = (BIO_F_BUFFER_CTX *)a->ptr;
135
8509
	free(b->ibuf);
136
8509
	free(b->obuf);
137
8509
	free(a->ptr);
138
8509
	a->ptr = NULL;
139
8509
	a->init = 0;
140
8509
	a->flags = 0;
141
8509
	return (1);
142
8509
}
143
144
static int
145
buffer_read(BIO *b, char *out, int outl)
146
{
147
	int i, num = 0;
148
	BIO_F_BUFFER_CTX *ctx;
149
150
8
	if (out == NULL)
151
		return (0);
152
4
	ctx = (BIO_F_BUFFER_CTX *)b->ptr;
153
154

8
	if ((ctx == NULL) || (b->next_bio == NULL))
155
		return (0);
156
	num = 0;
157
4
	BIO_clear_retry_flags(b);
158
159
start:
160
4
	i = ctx->ibuf_len;
161
	/* If there is stuff left over, grab it */
162
4
	if (i != 0) {
163
4
		if (i > outl)
164
2
			i = outl;
165
4
		memcpy(out, &(ctx->ibuf[ctx->ibuf_off]), i);
166
4
		ctx->ibuf_off += i;
167
4
		ctx->ibuf_len -= i;
168
4
		num += i;
169
4
		if (outl == i)
170
4
			return (num);
171
		outl -= i;
172
		out += i;
173
	}
174
175
	/* We may have done a partial read. try to do more.
176
	 * We have nothing in the buffer.
177
	 * If we get an error and have read some data, just return it
178
	 * and let them retry to get the error again.
179
	 * copy direct to parent address space */
180
	if (outl > ctx->ibuf_size) {
181
		for (;;) {
182
			i = BIO_read(b->next_bio, out, outl);
183
			if (i <= 0) {
184
				BIO_copy_next_retry(b);
185
				if (i < 0)
186
					return ((num > 0) ? num : i);
187
				if (i == 0)
188
					return (num);
189
			}
190
			num += i;
191
			if (outl == i)
192
				return (num);
193
			out += i;
194
			outl -= i;
195
		}
196
	}
197
	/* else */
198
199
	/* we are going to be doing some buffering */
200
	i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size);
201
	if (i <= 0) {
202
		BIO_copy_next_retry(b);
203
		if (i < 0)
204
			return ((num > 0) ? num : i);
205
		if (i == 0)
206
			return (num);
207
	}
208
	ctx->ibuf_off = 0;
209
	ctx->ibuf_len = i;
210
211
	/* Lets re-read using ourselves :-) */
212
	goto start;
213
4
}
214
215
static int
216
buffer_write(BIO *b, const char *in, int inl)
217
{
218
	int i, num = 0;
219
	BIO_F_BUFFER_CTX *ctx;
220
221
39226
	if ((in == NULL) || (inl <= 0))
222
		return (0);
223
19613
	ctx = (BIO_F_BUFFER_CTX *)b->ptr;
224

39226
	if ((ctx == NULL) || (b->next_bio == NULL))
225
		return (0);
226
227
19613
	BIO_clear_retry_flags(b);
228
start:
229
19613
	i = ctx->obuf_size - (ctx->obuf_len + ctx->obuf_off);
230
	/* add to buffer and return */
231
19613
	if (i >= inl) {
232
19613
		memcpy(&(ctx->obuf[ctx->obuf_off + ctx->obuf_len]), in, inl);
233
19613
		ctx->obuf_len += inl;
234
19613
		return (num + inl);
235
	}
236
	/* else */
237
	/* stuff already in buffer, so add to it first, then flush */
238
	if (ctx->obuf_len != 0) {
239
		if (i > 0) /* lets fill it up if we can */
240
		{
241
			memcpy(&(ctx->obuf[ctx->obuf_off + ctx->obuf_len]), in, i);
242
			in += i;
243
			inl -= i;
244
			num += i;
245
			ctx->obuf_len += i;
246
		}
247
		/* we now have a full buffer needing flushing */
248
		for (;;) {
249
			i = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]),
250
			    ctx->obuf_len);
251
			if (i <= 0) {
252
				BIO_copy_next_retry(b);
253
254
				if (i < 0)
255
					return ((num > 0) ? num : i);
256
				if (i == 0)
257
					return (num);
258
			}
259
			ctx->obuf_off += i;
260
			ctx->obuf_len -= i;
261
			if (ctx->obuf_len == 0)
262
				break;
263
		}
264
	}
265
	/* we only get here if the buffer has been flushed and we
266
	 * still have stuff to write */
267
	ctx->obuf_off = 0;
268
269
	/* we now have inl bytes to write */
270
	while (inl >= ctx->obuf_size) {
271
		i = BIO_write(b->next_bio, in, inl);
272
		if (i <= 0) {
273
			BIO_copy_next_retry(b);
274
			if (i < 0)
275
				return ((num > 0) ? num : i);
276
			if (i == 0)
277
				return (num);
278
		}
279
		num += i;
280
		in += i;
281
		inl -= i;
282
		if (inl == 0)
283
			return (num);
284
	}
285
286
	/* copy the rest into the buffer since we have only a small
287
	 * amount left */
288
	goto start;
289
19613
}
290
291
static long
292
buffer_ctrl(BIO *b, int cmd, long num, void *ptr)
293
{
294
	BIO *dbio;
295
	BIO_F_BUFFER_CTX *ctx;
296
	long ret = 1;
297
	char *p1, *p2;
298
	int r, i, *ip;
299
	int ibs, obs;
300
301
89778
	ctx = (BIO_F_BUFFER_CTX *)b->ptr;
302
303


44889
	switch (cmd) {
304
	case BIO_CTRL_RESET:
305
8485
		ctx->ibuf_off = 0;
306
8485
		ctx->ibuf_len = 0;
307
8485
		ctx->obuf_off = 0;
308
8485
		ctx->obuf_len = 0;
309
8485
		if (b->next_bio == NULL)
310
8485
			return (0);
311
		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
312
		break;
313
	case BIO_CTRL_INFO:
314
		ret = (long)ctx->obuf_len;
315
		break;
316
	case BIO_C_GET_BUFF_NUM_LINES:
317
		ret = 0;
318
		p1 = ctx->ibuf;
319
		for (i = 0; i < ctx->ibuf_len; i++) {
320
			if (p1[ctx->ibuf_off + i] == '\n')
321
				ret++;
322
		}
323
		break;
324
	case BIO_CTRL_WPENDING:
325
516
		ret = (long)ctx->obuf_len;
326
516
		if (ret == 0) {
327
144
			if (b->next_bio == NULL)
328
				return (0);
329
144
			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
330
144
		}
331
		break;
332
	case BIO_CTRL_PENDING:
333
		ret = (long)ctx->ibuf_len;
334
		if (ret == 0) {
335
			if (b->next_bio == NULL)
336
				return (0);
337
			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
338
		}
339
		break;
340
	case BIO_C_SET_BUFF_READ_DATA:
341
		if (num > ctx->ibuf_size) {
342
			p1 = malloc(num);
343
			if (p1 == NULL)
344
				goto malloc_error;
345
			free(ctx->ibuf);
346
			ctx->ibuf = p1;
347
		}
348
		ctx->ibuf_off = 0;
349
		ctx->ibuf_len = (int)num;
350
		memcpy(ctx->ibuf, ptr, num);
351
		ret = 1;
352
		break;
353
	case BIO_C_SET_BUFF_SIZE:
354
8489
		if (ptr != NULL) {
355
8489
			ip = (int *)ptr;
356
8489
			if (*ip == 0) {
357
8487
				ibs = (int)num;
358
8487
				obs = ctx->obuf_size;
359
8487
			}
360
			else /* if (*ip == 1) */
361
			{
362
2
				ibs = ctx->ibuf_size;
363
2
				obs = (int)num;
364
			}
365
		} else {
366
			ibs = (int)num;
367
			obs = (int)num;
368
		}
369
8489
		p1 = ctx->ibuf;
370
8489
		p2 = ctx->obuf;
371

8489
		if ((ibs > DEFAULT_BUFFER_SIZE) && (ibs != ctx->ibuf_size)) {
372
			p1 = malloc(num);
373
			if (p1 == NULL)
374
				goto malloc_error;
375
		}
376

8489
		if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) {
377
			p2 = malloc(num);
378
			if (p2 == NULL) {
379
				if (p1 != ctx->ibuf)
380
					free(p1);
381
				goto malloc_error;
382
			}
383
		}
384
8489
		if (ctx->ibuf != p1) {
385
			free(ctx->ibuf);
386
			ctx->ibuf = p1;
387
			ctx->ibuf_off = 0;
388
			ctx->ibuf_len = 0;
389
			ctx->ibuf_size = ibs;
390
		}
391
8489
		if (ctx->obuf != p2) {
392
			free(ctx->obuf);
393
			ctx->obuf = p2;
394
			ctx->obuf_off = 0;
395
			ctx->obuf_len = 0;
396
			ctx->obuf_size = obs;
397
		}
398
		break;
399
	case BIO_C_DO_STATE_MACHINE:
400
		if (b->next_bio == NULL)
401
			return (0);
402
		BIO_clear_retry_flags(b);
403
		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
404
		BIO_copy_next_retry(b);
405
		break;
406
407
	case BIO_CTRL_FLUSH:
408
10289
		if (b->next_bio == NULL)
409
			return (0);
410
10289
		if (ctx->obuf_len <= 0) {
411
18
			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
412
18
			break;
413
		}
414
415
9527
		for (;;) {
416
19798
			BIO_clear_retry_flags(b);
417
19798
			if (ctx->obuf_len > 0) {
418
22062
				r = BIO_write(b->next_bio,
419
11031
				    &(ctx->obuf[ctx->obuf_off]),
420
				    ctx->obuf_len);
421
11031
				BIO_copy_next_retry(b);
422
11031
				if (r <= 0)
423
1504
					return ((long)r);
424
9527
				ctx->obuf_off += r;
425
9527
				ctx->obuf_len -= r;
426
			} else {
427
8767
				ctx->obuf_len = 0;
428
8767
				ctx->obuf_off = 0;
429
				break;
430
			}
431
		}
432
8767
		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
433
8767
		break;
434
	case BIO_CTRL_DUP:
435
2
		dbio = (BIO *)ptr;
436

4
		if (!BIO_set_read_buffer_size(dbio, ctx->ibuf_size) ||
437
2
		    !BIO_set_write_buffer_size(dbio, ctx->obuf_size))
438
			ret = 0;
439
		break;
440
	default:
441
17108
		if (b->next_bio == NULL)
442
			return (0);
443
17108
		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
444
17108
		break;
445
	}
446
34900
	return (ret);
447
malloc_error:
448
	BIOerror(ERR_R_MALLOC_FAILURE);
449
	return (0);
450
44889
}
451
452
static long
453
buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
454
{
455
	long ret = 1;
456
457
	if (b->next_bio == NULL)
458
		return (0);
459
	switch (cmd) {
460
	default:
461
		ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
462
		break;
463
	}
464
	return (ret);
465
}
466
467
static int
468
buffer_gets(BIO *b, char *buf, int size)
469
{
470
	BIO_F_BUFFER_CTX *ctx;
471
	int num = 0, i, flag;
472
	char *p;
473
474
16
	ctx = (BIO_F_BUFFER_CTX *)b->ptr;
475
8
	size--; /* reserve space for a '\0' */
476
8
	BIO_clear_retry_flags(b);
477
478
8
	for (;;) {
479
10
		if (ctx->ibuf_len > 0) {
480
8
			p = &(ctx->ibuf[ctx->ibuf_off]);
481
			flag = 0;
482

480
			for (i = 0; (i < ctx->ibuf_len) && (i < size); i++) {
483
160
				*(buf++) = p[i];
484
160
				if (p[i] == '\n') {
485
					flag = 1;
486
8
					i++;
487
8
					break;
488
				}
489
			}
490
8
			num += i;
491
8
			size -= i;
492
8
			ctx->ibuf_len -= i;
493
8
			ctx->ibuf_off += i;
494
8
			if (flag || size == 0) {
495
8
				*buf = '\0';
496
8
				return (num);
497
			}
498
		}
499
		else	/* read another chunk */
500
		{
501
2
			i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size);
502
2
			if (i <= 0) {
503
				BIO_copy_next_retry(b);
504
				*buf = '\0';
505
				if (i < 0)
506
					return ((num > 0) ? num : i);
507
				if (i == 0)
508
					return (num);
509
			}
510
2
			ctx->ibuf_len = i;
511
2
			ctx->ibuf_off = 0;
512
		}
513
	}
514
8
}
515
516
static int
517
buffer_puts(BIO *b, const char *str)
518
{
519
	return (buffer_write(b, str, strlen(str)));
520
}