]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/bio/bio_lib.c
Tweaks based on review feedback of BIO size_t work
[thirdparty/openssl.git] / crypto / bio / bio_lib.c
CommitLineData
b1322259
RS
1/*
2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
d02b48c6 3 *
b1322259
RS
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
d02b48c6
RE
8 */
9
10#include <stdio.h>
11#include <errno.h>
ec577822 12#include <openssl/crypto.h>
a146ae55 13#include "bio_lcl.h"
b39fc560 14#include "internal/cryptlib.h"
58964a49 15
98e553d2
MC
16
17/*
18 * Helper macro for the callback to determine whether an operator expects a
19 * len parameter or not
20 */
21#define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE || \
22 (o) == BIO_CB_GETS)
23
24/*
25 * Helper function to work out whether to call the new style callback or the old
26 * one, and translate between the two.
27 *
28 * This has a long return type for consistency with the old callback. Similarly
29 * for the "long" used for "inret"
30 */
31static long bio_call_callback(BIO *b, int oper, const char *argp, size_t len,
32 int argi, long argl, long inret, size_t *processed)
33{
34 long ret;
35 int bareoper;
36
37 if (b->callback_ex != NULL) {
38 return b->callback_ex(b, oper, argp, len, argi, argl, inret, processed);
39 }
40
41 /* Strip off any BIO_CB_RETURN flag */
42 bareoper = oper & ~BIO_CB_RETURN;
43
44 /*
45 * We have an old style callback, so we will have to do nasty casts and
46 * check for overflows.
47 */
48 if (HAS_LEN_OPER(bareoper)) {
49 /* In this case |len| is set, and should be used instead of |argi| */
50 if (len > INT_MAX)
51 return -1;
52
53 argi = (int)len;
54
55 if (inret && (oper & BIO_CB_RETURN)) {
56 if (*processed > INT_MAX)
57 return -1;
58 inret = *processed;
59 }
60 }
61
62 ret = b->callback(b, oper, argp, argi, argl, inret);
63
64 if (ret > LONG_MAX || ret < LONG_MIN)
65 return -1;
66
67 if (ret >= 0 && (HAS_LEN_OPER(bareoper) || bareoper == BIO_CB_PUTS)) {
68 *processed = (size_t)ret;
69 ret = 1;
70 }
71
72 return ret;
73}
74
04f6b0fd 75BIO *BIO_new(const BIO_METHOD *method)
0f113f3e 76{
9d7bfb14 77 BIO *bio = OPENSSL_zalloc(sizeof(*bio));
0f113f3e 78
9d7bfb14 79 if (bio == NULL) {
0f113f3e
MC
80 BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
81 return (NULL);
82 }
d02b48c6 83
0f113f3e 84 bio->method = method;
0f113f3e 85 bio->shutdown = 1;
0f113f3e 86 bio->references = 1;
9d7bfb14 87
25a807bc 88 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data))
9d7bfb14 89 goto err;
fb46be03
AG
90
91 bio->lock = CRYPTO_THREAD_lock_new();
92 if (bio->lock == NULL) {
9d7bfb14 93 BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
fb46be03 94 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
9d7bfb14 95 goto err;
fb46be03
AG
96 }
97
9d7bfb14
F
98 if (method->create != NULL && !method->create(bio)) {
99 BIOerr(BIO_F_BIO_NEW, ERR_R_INIT_FAIL);
100 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
101 CRYPTO_THREAD_lock_free(bio->lock);
102 goto err;
fb46be03
AG
103 }
104
9d7bfb14
F
105 return bio;
106
107err:
108 OPENSSL_free(bio);
109 return NULL;
0f113f3e 110}
d02b48c6 111
6b691a5c 112int BIO_free(BIO *a)
0f113f3e 113{
98e553d2 114 int ret;
d02b48c6 115
0f113f3e 116 if (a == NULL)
fb46be03
AG
117 return 0;
118
98e553d2 119 if (CRYPTO_atomic_add(&a->references, -1, &ret, a->lock) <= 0)
fb46be03 120 return 0;
d02b48c6 121
f3f1cf84 122 REF_PRINT_COUNT("BIO", a);
98e553d2 123 if (ret > 0)
fb46be03 124 return 1;
98e553d2
MC
125 REF_ASSERT_ISNT(ret < 0);
126
127 if (a->callback != NULL || a->callback_ex != NULL) {
128 ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL);
129 if (ret <= 0)
130 return ret;
131 }
d02b48c6 132
a14a740d
F
133 if ((a->method != NULL) && (a->method->destroy != NULL))
134 a->method->destroy(a);
135
0f113f3e 136 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
58964a49 137
fb46be03
AG
138 CRYPTO_THREAD_lock_free(a->lock);
139
0f113f3e 140 OPENSSL_free(a);
fb46be03
AG
141
142 return 1;
0f113f3e 143}
d02b48c6 144
a146ae55
MC
145void BIO_set_data(BIO *a, void *ptr)
146{
147 a->ptr = ptr;
148}
149
150void *BIO_get_data(BIO *a)
151{
152 return a->ptr;
153}
154
155void BIO_set_init(BIO *a, int init)
156{
157 a->init = init;
158}
159
160int BIO_get_init(BIO *a)
161{
162 return a->init;
163}
164
165void BIO_set_shutdown(BIO *a, int shut)
166{
167 a->shutdown = shut;
168}
169
170int BIO_get_shutdown(BIO *a)
171{
172 return a->shutdown;
173}
174
371acb22 175void BIO_vfree(BIO *a)
0f113f3e
MC
176{
177 BIO_free(a);
178}
371acb22 179
fb46be03
AG
180int BIO_up_ref(BIO *a)
181{
182 int i;
183
184 if (CRYPTO_atomic_add(&a->references, 1, &i, a->lock) <= 0)
185 return 0;
186
187 REF_PRINT_COUNT("BIO", a);
188 REF_ASSERT_ISNT(i < 2);
189 return ((i > 1) ? 1 : 0);
190}
191
7806f3dd 192void BIO_clear_flags(BIO *b, int flags)
0f113f3e
MC
193{
194 b->flags &= ~flags;
195}
196
197int BIO_test_flags(const BIO *b, int flags)
198{
199 return (b->flags & flags);
200}
201
202void BIO_set_flags(BIO *b, int flags)
203{
204 b->flags |= flags;
205}
206
d07aee2c
MC
207BIO_callback_fn BIO_get_callback(const BIO *b)
208{
0f113f3e
MC
209 return b->callback;
210}
211
d07aee2c 212void BIO_set_callback(BIO *b, BIO_callback_fn cb)
0f113f3e
MC
213{
214 b->callback = cb;
215}
7806f3dd 216
d07aee2c
MC
217BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b)
218{
219 return b->callback_ex;
220}
221
222void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb)
223{
224 b->callback_ex = cb;
225}
226
7806f3dd 227void BIO_set_callback_arg(BIO *b, char *arg)
0f113f3e
MC
228{
229 b->cb_arg = arg;
230}
7806f3dd 231
0f113f3e
MC
232char *BIO_get_callback_arg(const BIO *b)
233{
234 return b->cb_arg;
235}
7806f3dd 236
0f113f3e
MC
237const char *BIO_method_name(const BIO *b)
238{
239 return b->method->name;
240}
7806f3dd
NL
241
242int BIO_method_type(const BIO *b)
0f113f3e
MC
243{
244 return b->method->type;
245}
7806f3dd 246
bb5310be
MC
247/*
248 * This is essentially the same as BIO_read_ex() except that it allows
249 * 0 or a -ve value to indicate failure (retryable or not) in the return. This
250 * is for compatibility with the old style BIO_read(), where existing code may
251 * make assumptions about the return value that it might get.
252 */
253static int bio_read_intern(BIO *b, void *out, size_t outl, size_t *read)
d07aee2c
MC
254{
255 int ret;
d02b48c6 256
0f113f3e 257 if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
d07aee2c 258 BIOerr(BIO_F_BIO_READ_EX, BIO_R_UNSUPPORTED_METHOD);
bb5310be 259 return -2;
0f113f3e 260 }
d02b48c6 261
d07aee2c 262 if ((b->callback != NULL || b->callback_ex != NULL) &&
98e553d2
MC
263 ((ret = (int)bio_call_callback(b, BIO_CB_READ, out, outl, 0, 0L, 1L,
264 read)) <= 0))
d07aee2c 265 return ret;
d02b48c6 266
0f113f3e 267 if (!b->init) {
d07aee2c
MC
268 BIOerr(BIO_F_BIO_READ_EX, BIO_R_UNINITIALIZED);
269 return -2;
0f113f3e 270 }
d02b48c6 271
d07aee2c 272 ret = b->method->bread(b, out, outl, read);
dfeab068 273
d07aee2c
MC
274 if (ret > 0)
275 b->num_read += (uint64_t)*read;
276
277 if (b->callback != NULL || b->callback_ex != NULL)
98e553d2
MC
278 ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, out, outl,
279 0, 0L, ret, read);
d02b48c6 280
d07aee2c 281 return ret;
0f113f3e 282}
d02b48c6 283
bb5310be 284int BIO_read(BIO *b, void *out, int outl)
0f113f3e 285{
bb5310be 286 size_t read;
3befffa3
MC
287 int ret;
288
bb5310be 289 if (outl < 0)
3befffa3
MC
290 return 0;
291
bb5310be 292 ret = bio_read_intern(b, out, (size_t)outl, &read);
3befffa3
MC
293
294 if (ret > 0) {
bb5310be
MC
295 /* *read should always be <= outl */
296 ret = (int)read;
3befffa3
MC
297 }
298
299 return ret;
300}
301
bb5310be
MC
302int BIO_read_ex(BIO *b, void *out, size_t outl, size_t *read)
303{
304 int ret;
305
306 ret = bio_read_intern(b, out, outl, read);
307
308 if (ret > 0)
309 ret = 1;
310 else
311 ret = 0;
312
313 return ret;
314}
315
316static int bio_write_intern(BIO *b, const void *in, size_t inl, size_t *written)
3befffa3
MC
317{
318 int ret;
58964a49 319
0f113f3e 320 if (b == NULL)
bb5310be 321 return 0;
d02b48c6 322
0f113f3e 323 if ((b->method == NULL) || (b->method->bwrite == NULL)) {
3befffa3 324 BIOerr(BIO_F_BIO_WRITE_EX, BIO_R_UNSUPPORTED_METHOD);
bb5310be 325 return -2;
0f113f3e 326 }
d02b48c6 327
3befffa3 328 if ((b->callback != NULL || b->callback_ex != NULL) &&
98e553d2
MC
329 ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, in, inl, 0, 0L, 1L,
330 written)) <= 0))
3befffa3 331 return ret;
d02b48c6 332
0f113f3e 333 if (!b->init) {
3befffa3
MC
334 BIOerr(BIO_F_BIO_WRITE_EX, BIO_R_UNINITIALIZED);
335 return -2;
0f113f3e 336 }
d02b48c6 337
3befffa3 338 ret = b->method->bwrite(b, in, inl, written);
dfeab068 339
3befffa3
MC
340 if (ret > 0)
341 b->num_write += (uint64_t)*written;
d02b48c6 342
3befffa3 343 if (b->callback != NULL || b->callback_ex != NULL)
98e553d2
MC
344 ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, in, inl,
345 0, 0L, ret, written);
3befffa3
MC
346
347 return ret;
0f113f3e 348}
d02b48c6 349
bb5310be
MC
350int BIO_write(BIO *b, const void *in, int inl)
351{
352 size_t written;
353 int ret;
354
355 if (inl < 0)
356 return 0;
357
358 ret = bio_write_intern(b, in, (size_t)inl, &written);
359
360 if (ret > 0) {
361 /* *written should always be <= inl */
362 ret = (int)written;
363 }
364
365 return ret;
366}
367
368int BIO_write_ex(BIO *b, const void *in, size_t inl, size_t *written)
369{
370 int ret;
371
372 ret = bio_write_intern(b, in, inl, written);
373
374 if (ret > 0)
375 ret = 1;
376 else
377 ret = 0;
378
379 return ret;
380}
381
6b691a5c 382int BIO_puts(BIO *b, const char *in)
0f113f3e 383{
98e553d2 384 int ret;
47263ace 385 size_t written = 0;
d02b48c6 386
0f113f3e
MC
387 if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) {
388 BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD);
98e553d2 389 return -2;
0f113f3e 390 }
d02b48c6 391
98e553d2
MC
392 if (b->callback != NULL || b->callback_ex != NULL) {
393 ret = (int)bio_call_callback(b, BIO_CB_PUTS, in, 0, 0, 0L, 1L, NULL);
394 if (ret <= 0)
395 return ret;
396 }
d02b48c6 397
0f113f3e
MC
398 if (!b->init) {
399 BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED);
98e553d2 400 return -2;
0f113f3e 401 }
d02b48c6 402
98e553d2 403 ret = b->method->bputs(b, in);
d02b48c6 404
98e553d2
MC
405 if (ret > 0) {
406 b->num_write += (uint64_t)ret;
407 written = ret;
408 ret = 1;
409 }
410
411 if (b->callback != NULL || b->callback_ex != NULL)
412 ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, in, 0, 0,
413 0L, ret, &written);
414
415 if (ret > 0) {
416 if (written > INT_MAX)
417 ret = -1;
418 else
419 ret = (int)written;
420 }
7d95ff76 421
98e553d2 422 return ret;
0f113f3e 423}
d02b48c6 424
98e553d2 425int BIO_gets(BIO *b, char *out, int outl)
0f113f3e 426{
98e553d2 427 int ret;
47263ace 428 size_t read = 0;
0f113f3e
MC
429
430 if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) {
431 BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD);
432 return (-2);
433 }
434
98e553d2
MC
435 if (b->callback != NULL || b->callback_ex != NULL) {
436 ret = (int)bio_call_callback(b, BIO_CB_GETS, out, outl, 0, 0L, 1, NULL);
437 if (ret <= 0)
438 return ret;
439 }
0f113f3e
MC
440
441 if (!b->init) {
442 BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED);
443 return (-2);
444 }
445
98e553d2
MC
446 ret = b->method->bgets(b, out, outl);
447
448 if (ret > 0) {
449 read = ret;
450 ret = 1;
451 }
452
453 if (b->callback != NULL || b->callback_ex != NULL)
454 ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, out, outl,
455 0, 0L, ret, &read);
456
457 if (ret > 0) {
458 if (read > INT_MAX)
459 ret = -1;
460 else
461 ret = (int)read;
462 }
0f113f3e 463
98e553d2 464 return ret;
0f113f3e
MC
465}
466
467int BIO_indent(BIO *b, int indent, int max)
468{
469 if (indent < 0)
470 indent = 0;
471 if (indent > max)
472 indent = max;
473 while (indent--)
474 if (BIO_puts(b, " ") != 1)
475 return 0;
476 return 1;
477}
54a656ef 478
6b691a5c 479long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
0f113f3e
MC
480{
481 int i;
d02b48c6 482
0f113f3e
MC
483 i = iarg;
484 return (BIO_ctrl(b, cmd, larg, (char *)&i));
485}
d02b48c6 486
417be660 487void *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
0f113f3e 488{
417be660 489 void *p = NULL;
58964a49 490
0f113f3e
MC
491 if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
492 return (NULL);
493 else
494 return (p);
495}
58964a49 496
95d29597 497long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
0f113f3e
MC
498{
499 long ret;
d02b48c6 500
0f113f3e 501 if (b == NULL)
98e553d2 502 return 0;
d02b48c6 503
0f113f3e
MC
504 if ((b->method == NULL) || (b->method->ctrl == NULL)) {
505 BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD);
98e553d2 506 return -2;
0f113f3e 507 }
d02b48c6 508
98e553d2
MC
509 if (b->callback != NULL || b->callback_ex != NULL) {
510 ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL);
511 if (ret <= 0)
512 return ret;
513 }
d02b48c6 514
0f113f3e 515 ret = b->method->ctrl(b, cmd, larg, parg);
d02b48c6 516
98e553d2
MC
517 if (b->callback != NULL || b->callback_ex != NULL)
518 ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd,
519 larg, ret, NULL);
520
521 return ret;
0f113f3e 522}
d02b48c6 523
0f113f3e
MC
524long BIO_callback_ctrl(BIO *b, int cmd,
525 void (*fp) (struct bio_st *, int, const char *, int,
526 long, long))
527{
528 long ret;
d3442bc7 529
0f113f3e
MC
530 if (b == NULL)
531 return (0);
d3442bc7 532
0f113f3e
MC
533 if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) {
534 BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD);
535 return (-2);
536 }
d3442bc7 537
98e553d2
MC
538 if (b->callback != NULL || b->callback_ex != NULL) {
539 ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, cmd, 0, 1L,
540 NULL);
541 if (ret <= 0)
542 return ret;
543 }
d3442bc7 544
0f113f3e 545 ret = b->method->callback_ctrl(b, cmd, fp);
d3442bc7 546
98e553d2
MC
547 if (b->callback != NULL || b->callback_ex != NULL)
548 ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, 0,
549 cmd, 0, ret, NULL);
550
551 return ret;
0f113f3e 552}
d3442bc7 553
0f113f3e
MC
554/*
555 * It is unfortunate to duplicate in functions what the BIO_(w)pending macros
95d29597 556 * do; but those macros have inappropriate return type, and for interfacing
0f113f3e
MC
557 * from other programming languages, C macros aren't much of a help anyway.
558 */
95d29597 559size_t BIO_ctrl_pending(BIO *bio)
0f113f3e
MC
560{
561 return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
562}
95d29597
BM
563
564size_t BIO_ctrl_wpending(BIO *bio)
0f113f3e
MC
565{
566 return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
567}
95d29597 568
d02b48c6 569/* put the 'bio' on the end of b's list of operators */
6b691a5c 570BIO *BIO_push(BIO *b, BIO *bio)
0f113f3e
MC
571{
572 BIO *lb;
573
574 if (b == NULL)
575 return (bio);
576 lb = b;
577 while (lb->next_bio != NULL)
578 lb = lb->next_bio;
579 lb->next_bio = bio;
580 if (bio != NULL)
581 bio->prev_bio = lb;
582 /* called to do internal processing */
583 BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
584 return (b);
585}
d02b48c6
RE
586
587/* Remove the first and return the rest */
6b691a5c 588BIO *BIO_pop(BIO *b)
0f113f3e
MC
589{
590 BIO *ret;
d02b48c6 591
0f113f3e
MC
592 if (b == NULL)
593 return (NULL);
594 ret = b->next_bio;
d02b48c6 595
0f113f3e 596 BIO_ctrl(b, BIO_CTRL_POP, 0, b);
5d780bab 597
0f113f3e
MC
598 if (b->prev_bio != NULL)
599 b->prev_bio->next_bio = b->next_bio;
600 if (b->next_bio != NULL)
601 b->next_bio->prev_bio = b->prev_bio;
d02b48c6 602
0f113f3e
MC
603 b->next_bio = NULL;
604 b->prev_bio = NULL;
605 return (ret);
606}
d02b48c6 607
6b691a5c 608BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
0f113f3e
MC
609{
610 BIO *b, *last;
611
612 b = last = bio;
613 for (;;) {
614 if (!BIO_should_retry(b))
615 break;
616 last = b;
617 b = b->next_bio;
618 if (b == NULL)
619 break;
620 }
621 if (reason != NULL)
622 *reason = last->retry_reason;
623 return (last);
624}
d02b48c6 625
6b691a5c 626int BIO_get_retry_reason(BIO *bio)
0f113f3e
MC
627{
628 return (bio->retry_reason);
629}
d02b48c6 630
a146ae55
MC
631void BIO_set_retry_reason(BIO *bio, int reason)
632{
633 bio->retry_reason = reason;
634}
635
6b691a5c 636BIO *BIO_find_type(BIO *bio, int type)
0f113f3e
MC
637{
638 int mt, mask;
639
cc99bfa7 640 if (bio == NULL)
0f113f3e
MC
641 return NULL;
642 mask = type & 0xff;
643 do {
644 if (bio->method != NULL) {
645 mt = bio->method->type;
646
647 if (!mask) {
648 if (mt & type)
649 return (bio);
650 } else if (mt == type)
651 return (bio);
652 }
653 bio = bio->next_bio;
654 } while (bio != NULL);
655 return (NULL);
656}
d02b48c6 657
cfd3bb17 658BIO *BIO_next(BIO *b)
0f113f3e 659{
cc99bfa7 660 if (b == NULL)
0f113f3e
MC
661 return NULL;
662 return b->next_bio;
663}
cfd3bb17 664
a146ae55
MC
665void BIO_set_next(BIO *b, BIO *next)
666{
667 b->next_bio = next;
668}
669
6b691a5c 670void BIO_free_all(BIO *bio)
0f113f3e
MC
671{
672 BIO *b;
673 int ref;
674
675 while (bio != NULL) {
676 b = bio;
677 ref = b->references;
678 bio = bio->next_bio;
679 BIO_free(b);
680 /* Since ref count > 1, don't free anyone else. */
681 if (ref > 1)
682 break;
683 }
684}
d02b48c6 685
6b691a5c 686BIO *BIO_dup_chain(BIO *in)
0f113f3e
MC
687{
688 BIO *ret = NULL, *eoc = NULL, *bio, *new_bio;
689
690 for (bio = in; bio != NULL; bio = bio->next_bio) {
691 if ((new_bio = BIO_new(bio->method)) == NULL)
692 goto err;
693 new_bio->callback = bio->callback;
98e553d2 694 new_bio->callback_ex = bio->callback_ex;
0f113f3e
MC
695 new_bio->cb_arg = bio->cb_arg;
696 new_bio->init = bio->init;
697 new_bio->shutdown = bio->shutdown;
698 new_bio->flags = bio->flags;
699
700 /* This will let SSL_s_sock() work with stdin/stdout */
701 new_bio->num = bio->num;
702
703 if (!BIO_dup_state(bio, (char *)new_bio)) {
704 BIO_free(new_bio);
705 goto err;
706 }
707
708 /* copy app data */
709 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data,
aec54108
MC
710 &bio->ex_data)) {
711 BIO_free(new_bio);
0f113f3e 712 goto err;
aec54108 713 }
0f113f3e
MC
714
715 if (ret == NULL) {
716 eoc = new_bio;
717 ret = eoc;
718 } else {
719 BIO_push(eoc, new_bio);
720 eoc = new_bio;
721 }
722 }
723 return (ret);
724 err:
aec54108
MC
725 BIO_free_all(ret);
726
0f113f3e
MC
727 return (NULL);
728}
d02b48c6 729
6b691a5c 730void BIO_copy_next_retry(BIO *b)
0f113f3e
MC
731{
732 BIO_set_flags(b, BIO_get_retry_flags(b->next_bio));
733 b->retry_reason = b->next_bio->retry_reason;
734}
d02b48c6 735
dd9d233e 736int BIO_set_ex_data(BIO *bio, int idx, void *data)
0f113f3e
MC
737{
738 return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data));
739}
58964a49 740
dd9d233e 741void *BIO_get_ex_data(BIO *bio, int idx)
0f113f3e
MC
742{
743 return (CRYPTO_get_ex_data(&(bio->ex_data), idx));
744}
58964a49 745
b8b12aad 746uint64_t BIO_number_read(BIO *bio)
c3ed3b6e 747{
0f113f3e
MC
748 if (bio)
749 return bio->num_read;
750 return 0;
c3ed3b6e
DSH
751}
752
b8b12aad 753uint64_t BIO_number_written(BIO *bio)
c3ed3b6e 754{
0f113f3e
MC
755 if (bio)
756 return bio->num_write;
757 return 0;
c3ed3b6e 758}
ff234405 759
1ee7b8b9
MC
760void bio_free_ex_data(BIO *bio)
761{
762 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
763}
ff234405
MC
764
765void bio_cleanup(void)
766{
767#ifndef OPENSSL_NO_SOCK
768 bio_sock_cleanup_int();
769 CRYPTO_THREAD_lock_free(bio_lookup_lock);
770 bio_lookup_lock = NULL;
5a7ad1f0 771#endif
8b8d963d
RS
772 CRYPTO_THREAD_lock_free(bio_type_lock);
773 bio_type_lock = NULL;
ff234405 774}