GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/bio/bio_lib.c Lines: 170 260 65.4 %
Date: 2017-11-13 Branches: 80 166 48.2 %

Line Branch Exec Source
1
/* $OpenBSD: bio_lib.c,v 1.23 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
62
#include <openssl/bio.h>
63
#include <openssl/crypto.h>
64
#include <openssl/err.h>
65
#include <openssl/stack.h>
66
67
BIO *
68
BIO_new(BIO_METHOD *method)
69
{
70
	BIO *ret = NULL;
71
72
118686
	ret = malloc(sizeof(BIO));
73
59343
	if (ret == NULL) {
74
		BIOerror(ERR_R_MALLOC_FAILURE);
75
		return (NULL);
76
	}
77
59343
	if (!BIO_set(ret, method)) {
78
		free(ret);
79
		ret = NULL;
80
	}
81
59343
	return (ret);
82
59343
}
83
84
int
85
BIO_set(BIO *bio, BIO_METHOD *method)
86
{
87
118686
	bio->method = method;
88
59343
	bio->callback = NULL;
89
59343
	bio->cb_arg = NULL;
90
59343
	bio->init = 0;
91
59343
	bio->shutdown = 1;
92
59343
	bio->flags = 0;
93
59343
	bio->retry_reason = 0;
94
59343
	bio->num = 0;
95
59343
	bio->ptr = NULL;
96
59343
	bio->prev_bio = NULL;
97
59343
	bio->next_bio = NULL;
98
59343
	bio->references = 1;
99
59343
	bio->num_read = 0L;
100
59343
	bio->num_write = 0L;
101
59343
	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
102
59343
	if (method->create != NULL)
103
59331
		if (!method->create(bio)) {
104
			CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio,
105
			    &bio->ex_data);
106
			return (0);
107
		}
108
59343
	return (1);
109
59343
}
110
111
int
112
BIO_free(BIO *a)
113
{
114
	int i;
115
116
169000
	if (a == NULL)
117
24737
		return (0);
118
119
59763
	i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO);
120
59763
	if (i > 0)
121
438
		return (1);
122

59325
	if ((a->callback != NULL) &&
123
	    ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0))
124
		return (i);
125
126
59325
	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
127
128

118650
	if (a->method != NULL && a->method->destroy != NULL)
129
59313
		a->method->destroy(a);
130
59325
	free(a);
131
59325
	return (1);
132
84500
}
133
134
void
135
BIO_vfree(BIO *a)
136
{
137
	BIO_free(a);
138
}
139
140
void
141
BIO_clear_flags(BIO *b, int flags)
142
{
143
704600
	b->flags &= ~flags;
144
352300
}
145
146
int
147
BIO_test_flags(const BIO *b, int flags)
148
{
149
90254
	return (b->flags & flags);
150
}
151
152
void
153
BIO_set_flags(BIO *b, int flags)
154
{
155
80954
	b->flags |= flags;
156
40477
}
157
158
long
159
(*BIO_get_callback(const BIO *b))(struct bio_st *, int, const char *, int,
160
    long, long)
161
{
162
4
	return b->callback;
163
}
164
165
void
166
BIO_set_callback(BIO *b, long (*cb)(struct bio_st *, int, const char *, int,
167
    long, long))
168
{
169
4
	b->callback = cb;
170
2
}
171
172
void
173
BIO_set_callback_arg(BIO *b, char *arg)
174
{
175
4
	b->cb_arg = arg;
176
2
}
177
178
char *
179
BIO_get_callback_arg(const BIO *b)
180
{
181
4
	return b->cb_arg;
182
}
183
184
const char *
185
BIO_method_name(const BIO *b)
186
{
187
	return b->method->name;
188
}
189
190
int
191
BIO_method_type(const BIO *b)
192
{
193
40
	return b->method->type;
194
}
195
196
int
197
BIO_read(BIO *b, void *out, int outl)
198
{
199
	int i;
200
	long (*cb)(BIO *, int, const char *, int, long, long);
201
202

517920
	if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
203
		BIOerror(BIO_R_UNSUPPORTED_METHOD);
204
		return (-2);
205
	}
206
207
129480
	cb = b->callback;
208

129480
	if ((cb != NULL) &&
209
	    ((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0))
210
		return (i);
211
212
129480
	if (!b->init) {
213
		BIOerror(BIO_R_UNINITIALIZED);
214
		return (-2);
215
	}
216
217
129480
	i = b->method->bread(b, out, outl);
218
219
129480
	if (i > 0)
220
116506
		b->num_read += (unsigned long)i;
221
222
129480
	if (cb != NULL)
223
		i = (int)cb(b, BIO_CB_READ|BIO_CB_RETURN, out, outl,
224
		    0L, (long)i);
225
129480
	return (i);
226
129480
}
227
228
int
229
BIO_write(BIO *b, const void *in, int inl)
230
{
231
	int i;
232
	long (*cb)(BIO *, int, const char *, int, long, long);
233
234
5378756
	if (b == NULL)
235
		return (0);
236
237
2689378
	cb = b->callback;
238

5378756
	if ((b->method == NULL) || (b->method->bwrite == NULL)) {
239
		BIOerror(BIO_R_UNSUPPORTED_METHOD);
240
		return (-2);
241
	}
242
243

2689378
	if ((cb != NULL) &&
244
	    ((i = (int)cb(b, BIO_CB_WRITE, in, inl, 0L, 1L)) <= 0))
245
		return (i);
246
247
2689378
	if (!b->init) {
248
144
		BIOerror(BIO_R_UNINITIALIZED);
249
144
		return (-2);
250
	}
251
252
2689234
	i = b->method->bwrite(b, in, inl);
253
254
2689234
	if (i > 0)
255
2683312
		b->num_write += (unsigned long)i;
256
257
2689234
	if (cb != NULL)
258
		i = (int)cb(b, BIO_CB_WRITE|BIO_CB_RETURN, in, inl,
259
		    0L, (long)i);
260
2689234
	return (i);
261
2689378
}
262
263
int
264
BIO_puts(BIO *b, const char *in)
265
{
266
	int i;
267
	long (*cb)(BIO *, int, const char *, int, long, long);
268
269

253088
	if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) {
270
		BIOerror(BIO_R_UNSUPPORTED_METHOD);
271
		return (-2);
272
	}
273
274
63272
	cb = b->callback;
275
276

63272
	if ((cb != NULL) &&
277
	    ((i = (int)cb(b, BIO_CB_PUTS, in, 0, 0L, 1L)) <= 0))
278
		return (i);
279
280
63272
	if (!b->init) {
281
		BIOerror(BIO_R_UNINITIALIZED);
282
		return (-2);
283
	}
284
285
63272
	i = b->method->bputs(b, in);
286
287
63272
	if (i > 0)
288
63272
		b->num_write += (unsigned long)i;
289
290
63272
	if (cb != NULL)
291
		i = (int)cb(b, BIO_CB_PUTS|BIO_CB_RETURN, in, 0, 0L, (long)i);
292
63272
	return (i);
293
63272
}
294
295
int
296
BIO_gets(BIO *b, char *in, int inl)
297
{
298
	int i;
299
	long (*cb)(BIO *, int, const char *, int, long, long);
300
301

2199980
	if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) {
302
		BIOerror(BIO_R_UNSUPPORTED_METHOD);
303
		return (-2);
304
	}
305
306
549995
	cb = b->callback;
307
308

549995
	if ((cb != NULL) &&
309
	    ((i = (int)cb(b, BIO_CB_GETS, in, inl, 0L, 1L)) <= 0))
310
		return (i);
311
312
549995
	if (!b->init) {
313
		BIOerror(BIO_R_UNINITIALIZED);
314
		return (-2);
315
	}
316
317
549995
	i = b->method->bgets(b, in, inl);
318
319
549995
	if (cb != NULL)
320
		i = (int)cb(b, BIO_CB_GETS|BIO_CB_RETURN, in, inl, 0L, (long)i);
321
549995
	return (i);
322
549995
}
323
324
int
325
BIO_indent(BIO *b, int indent, int max)
326
{
327
14912
	if (indent < 0)
328
		indent = 0;
329
7456
	if (indent > max)
330
		indent = max;
331
87246
	while (indent--)
332
36167
		if (BIO_puts(b, " ") != 1)
333
			return 0;
334
7456
	return 1;
335
7456
}
336
337
long
338
BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
339
{
340
32256
	int i;
341
342
16128
	i = iarg;
343
32256
	return (BIO_ctrl(b, cmd, larg, (char *)&i));
344
16128
}
345
346
char *
347
BIO_ptr_ctrl(BIO *b, int cmd, long larg)
348
{
349
	char *p = NULL;
350
351
	if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
352
		return (NULL);
353
	else
354
		return (p);
355
}
356
357
long
358
BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
359
{
360
	long ret;
361
	long (*cb)(BIO *, int, const char *, int, long, long);
362
363
542574
	if (b == NULL)
364
24
		return (0);
365
366

542526
	if ((b->method == NULL) || (b->method->ctrl == NULL)) {
367
		BIOerror(BIO_R_UNSUPPORTED_METHOD);
368
		return (-2);
369
	}
370
371
271263
	cb = b->callback;
372
373

271263
	if ((cb != NULL) &&
374
	    ((ret = cb(b, BIO_CB_CTRL, parg, cmd, larg, 1L)) <= 0))
375
		return (ret);
376
377
271263
	ret = b->method->ctrl(b, cmd, larg, parg);
378
379
271263
	if (cb != NULL)
380
		ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, parg, cmd, larg, ret);
381
271263
	return (ret);
382
271287
}
383
384
long
385
BIO_callback_ctrl(BIO *b, int cmd,
386
    void (*fp)(struct bio_st *, int, const char *, int, long, long))
387
{
388
	long ret;
389
	long (*cb)(BIO *, int, const char *, int, long, long);
390
391
	if (b == NULL)
392
		return (0);
393
394
	if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) {
395
		BIOerror(BIO_R_UNSUPPORTED_METHOD);
396
		return (-2);
397
	}
398
399
	cb = b->callback;
400
401
	if ((cb != NULL) &&
402
	    ((ret = cb(b, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L)) <= 0))
403
		return (ret);
404
405
	ret = b->method->callback_ctrl(b, cmd, fp);
406
407
	if (cb != NULL)
408
		ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, (void *)&fp, cmd, 0, ret);
409
	return (ret);
410
}
411
412
/* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
413
 * do; but those macros have inappropriate return type, and for interfacing
414
 * from other programming languages, C macros aren't much of a help anyway. */
415
size_t
416
BIO_ctrl_pending(BIO *bio)
417
{
418
10908
	return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
419
}
420
421
size_t
422
BIO_ctrl_wpending(BIO *bio)
423
{
424
	return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
425
}
426
427
428
/* put the 'bio' on the end of b's list of operators */
429
BIO *
430
BIO_push(BIO *b, BIO *bio)
431
{
432
	BIO *lb;
433
434
35464
	if (b == NULL)
435
		return (bio);
436
	lb = b;
437
35464
	while (lb->next_bio != NULL)
438
		lb = lb->next_bio;
439
17732
	lb->next_bio = bio;
440
17732
	if (bio != NULL)
441
17732
		bio->prev_bio = lb;
442
	/* called to do internal processing */
443
17732
	BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
444
17732
	return (b);
445
17732
}
446
447
/* Remove the first and return the rest */
448
BIO *
449
BIO_pop(BIO *b)
450
{
451
	BIO *ret;
452
453
32242
	if (b == NULL)
454
		return (NULL);
455
16121
	ret = b->next_bio;
456
457
16121
	BIO_ctrl(b, BIO_CTRL_POP, 0, b);
458
459
16121
	if (b->prev_bio != NULL)
460
		b->prev_bio->next_bio = b->next_bio;
461
16121
	if (b->next_bio != NULL)
462
16121
		b->next_bio->prev_bio = b->prev_bio;
463
464
16121
	b->next_bio = NULL;
465
16121
	b->prev_bio = NULL;
466
16121
	return (ret);
467
16121
}
468
469
BIO *
470
BIO_get_retry_BIO(BIO *bio, int *reason)
471
{
472
	BIO *b, *last;
473
474
	b = last = bio;
475
	for (;;) {
476
		if (!BIO_should_retry(b))
477
			break;
478
		last = b;
479
		b = b->next_bio;
480
		if (b == NULL)
481
			break;
482
	}
483
	if (reason != NULL)
484
		*reason = last->retry_reason;
485
	return (last);
486
}
487
488
int
489
BIO_get_retry_reason(BIO *bio)
490
{
491
	return (bio->retry_reason);
492
}
493
494
BIO *
495
BIO_find_type(BIO *bio, int type)
496
{
497
	int mt, mask;
498
499
62780
	if (!bio)
500
		return NULL;
501
31390
	mask = type & 0xff;
502
31390
	do {
503
31398
		if (bio->method != NULL) {
504
31398
			mt = bio->method->type;
505
31398
			if (!mask) {
506
31362
				if (mt & type)
507
31362
					return (bio);
508
36
			} else if (mt == type)
509
28
				return (bio);
510
		}
511
8
		bio = bio->next_bio;
512
8
	} while (bio != NULL);
513
	return (NULL);
514
31390
}
515
516
BIO *
517
BIO_next(BIO *b)
518
{
519
	if (!b)
520
		return NULL;
521
	return b->next_bio;
522
}
523
524
void
525
BIO_free_all(BIO *bio)
526
{
527
	BIO *b;
528
	int ref;
529
530
97538
	while (bio != NULL) {
531
		b = bio;
532
18778
		ref = b->references;
533
18778
		bio = bio->next_bio;
534
18778
		BIO_free(b);
535
		/* Since ref count > 1, don't free anyone else. */
536
18778
		if (ref > 1)
537
			break;
538
	}
539
20046
}
540
541
BIO *
542
BIO_dup_chain(BIO *in)
543
{
544
	BIO *ret = NULL, *eoc = NULL, *bio, *new_bio;
545
546
10
	for (bio = in; bio != NULL; bio = bio->next_bio) {
547
2
		if ((new_bio = BIO_new(bio->method)) == NULL)
548
			goto err;
549
2
		new_bio->callback = bio->callback;
550
2
		new_bio->cb_arg = bio->cb_arg;
551
2
		new_bio->init = bio->init;
552
2
		new_bio->shutdown = bio->shutdown;
553
2
		new_bio->flags = bio->flags;
554
555
		/* This will let SSL_s_sock() work with stdin/stdout */
556
2
		new_bio->num = bio->num;
557
558
2
		if (!BIO_dup_state(bio, (char *)new_bio)) {
559
			BIO_free(new_bio);
560
			goto err;
561
		}
562
563
		/* copy app data */
564
2
		if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO,
565
2
		    &new_bio->ex_data, &bio->ex_data))
566
			goto err;
567
568
2
		if (ret == NULL) {
569
			eoc = new_bio;
570
			ret = eoc;
571
2
		} else {
572
			BIO_push(eoc, new_bio);
573
			eoc = new_bio;
574
		}
575
	}
576
2
	return (ret);
577
err:
578
	BIO_free(ret);
579
	return (NULL);
580
581
2
}
582
583
void
584
BIO_copy_next_retry(BIO *b)
585
{
586
45660
	BIO_set_flags(b, BIO_get_retry_flags(b->next_bio));
587
22830
	b->retry_reason = b->next_bio->retry_reason;
588
22830
}
589
590
int
591
BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
592
    CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
593
{
594
	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
595
	    new_func, dup_func, free_func);
596
}
597
598
int
599
BIO_set_ex_data(BIO *bio, int idx, void *data)
600
{
601
	return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data));
602
}
603
604
void *
605
BIO_get_ex_data(BIO *bio, int idx)
606
{
607
	return (CRYPTO_get_ex_data(&(bio->ex_data), idx));
608
}
609
610
unsigned long
611
BIO_number_read(BIO *bio)
612
{
613
8
	if (bio)
614
4
		return bio->num_read;
615
	return 0;
616
4
}
617
618
unsigned long
619
BIO_number_written(BIO *bio)
620
{
621
8
	if (bio)
622
4
		return bio->num_write;
623
	return 0;
624
4
}