]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/bio/bio_lib.c
Read up to INT_MAX when calling legacy BIO_read() implementations
[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
61f5b6f3 247int BIO_read(BIO *b, void *out, int outl)
0f113f3e 248{
d07aee2c
MC
249 size_t read;
250 int ret;
251
252 if (outl < 0)
253 return 0;
254
255 ret = BIO_read_ex(b, out, (size_t)outl, &read);
256
257 if (ret > 0) {
258 /* *read should always be <= outl */
259 ret = (int)read;
260 }
261
262 return ret;
263}
264
265int BIO_read_ex(BIO *b, void *out, size_t outl, size_t *read)
266{
267 int ret;
d02b48c6 268
0f113f3e 269 if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
d07aee2c 270 BIOerr(BIO_F_BIO_READ_EX, BIO_R_UNSUPPORTED_METHOD);
0f113f3e
MC
271 return (-2);
272 }
d02b48c6 273
d07aee2c 274 if ((b->callback != NULL || b->callback_ex != NULL) &&
98e553d2
MC
275 ((ret = (int)bio_call_callback(b, BIO_CB_READ, out, outl, 0, 0L, 1L,
276 read)) <= 0))
d07aee2c 277 return ret;
d02b48c6 278
0f113f3e 279 if (!b->init) {
d07aee2c
MC
280 BIOerr(BIO_F_BIO_READ_EX, BIO_R_UNINITIALIZED);
281 return -2;
0f113f3e 282 }
d02b48c6 283
d07aee2c 284 ret = b->method->bread(b, out, outl, read);
dfeab068 285
d07aee2c
MC
286 if (ret > 0)
287 b->num_read += (uint64_t)*read;
288
289 if (b->callback != NULL || b->callback_ex != NULL)
98e553d2
MC
290 ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, out, outl,
291 0, 0L, ret, read);
d02b48c6 292
d07aee2c 293 return ret;
0f113f3e 294}
d02b48c6 295
6343829a 296int BIO_write(BIO *b, const void *in, int inl)
0f113f3e 297{
3befffa3
MC
298 size_t written;
299 int ret;
300
301 if (inl < 0)
302 return 0;
303
304 ret = BIO_write_ex(b, in, (size_t)inl, &written);
305
306 if (ret > 0) {
307 /* *written should always be <= inl */
308 ret = (int)written;
309 }
310
311 return ret;
312}
313
314int BIO_write_ex(BIO *b, const void *in, size_t inl, size_t *written)
315{
316 int ret;
58964a49 317
0f113f3e
MC
318 if (b == NULL)
319 return (0);
d02b48c6 320
0f113f3e 321 if ((b->method == NULL) || (b->method->bwrite == NULL)) {
3befffa3 322 BIOerr(BIO_F_BIO_WRITE_EX, BIO_R_UNSUPPORTED_METHOD);
0f113f3e
MC
323 return (-2);
324 }
d02b48c6 325
3befffa3 326 if ((b->callback != NULL || b->callback_ex != NULL) &&
98e553d2
MC
327 ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, in, inl, 0, 0L, 1L,
328 written)) <= 0))
3befffa3 329 return ret;
d02b48c6 330
0f113f3e 331 if (!b->init) {
3befffa3
MC
332 BIOerr(BIO_F_BIO_WRITE_EX, BIO_R_UNINITIALIZED);
333 return -2;
0f113f3e 334 }
d02b48c6 335
3befffa3 336 ret = b->method->bwrite(b, in, inl, written);
dfeab068 337
3befffa3
MC
338 if (ret > 0)
339 b->num_write += (uint64_t)*written;
d02b48c6 340
3befffa3 341 if (b->callback != NULL || b->callback_ex != NULL)
98e553d2
MC
342 ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, in, inl,
343 0, 0L, ret, written);
3befffa3
MC
344
345 return ret;
0f113f3e 346}
d02b48c6 347
6b691a5c 348int BIO_puts(BIO *b, const char *in)
0f113f3e 349{
98e553d2 350 int ret;
47263ace 351 size_t written = 0;
d02b48c6 352
0f113f3e
MC
353 if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) {
354 BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD);
98e553d2 355 return -2;
0f113f3e 356 }
d02b48c6 357
98e553d2
MC
358 if (b->callback != NULL || b->callback_ex != NULL) {
359 ret = (int)bio_call_callback(b, BIO_CB_PUTS, in, 0, 0, 0L, 1L, NULL);
360 if (ret <= 0)
361 return ret;
362 }
d02b48c6 363
0f113f3e
MC
364 if (!b->init) {
365 BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED);
98e553d2 366 return -2;
0f113f3e 367 }
d02b48c6 368
98e553d2 369 ret = b->method->bputs(b, in);
d02b48c6 370
98e553d2
MC
371 if (ret > 0) {
372 b->num_write += (uint64_t)ret;
373 written = ret;
374 ret = 1;
375 }
376
377 if (b->callback != NULL || b->callback_ex != NULL)
378 ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, in, 0, 0,
379 0L, ret, &written);
380
381 if (ret > 0) {
382 if (written > INT_MAX)
383 ret = -1;
384 else
385 ret = (int)written;
386 }
7d95ff76 387
98e553d2 388 return ret;
0f113f3e 389}
d02b48c6 390
98e553d2 391int BIO_gets(BIO *b, char *out, int outl)
0f113f3e 392{
98e553d2 393 int ret;
47263ace 394 size_t read = 0;
0f113f3e
MC
395
396 if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) {
397 BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD);
398 return (-2);
399 }
400
98e553d2
MC
401 if (b->callback != NULL || b->callback_ex != NULL) {
402 ret = (int)bio_call_callback(b, BIO_CB_GETS, out, outl, 0, 0L, 1, NULL);
403 if (ret <= 0)
404 return ret;
405 }
0f113f3e
MC
406
407 if (!b->init) {
408 BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED);
409 return (-2);
410 }
411
98e553d2
MC
412 ret = b->method->bgets(b, out, outl);
413
414 if (ret > 0) {
415 read = ret;
416 ret = 1;
417 }
418
419 if (b->callback != NULL || b->callback_ex != NULL)
420 ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, out, outl,
421 0, 0L, ret, &read);
422
423 if (ret > 0) {
424 if (read > INT_MAX)
425 ret = -1;
426 else
427 ret = (int)read;
428 }
0f113f3e 429
98e553d2 430 return ret;
0f113f3e
MC
431}
432
433int BIO_indent(BIO *b, int indent, int max)
434{
435 if (indent < 0)
436 indent = 0;
437 if (indent > max)
438 indent = max;
439 while (indent--)
440 if (BIO_puts(b, " ") != 1)
441 return 0;
442 return 1;
443}
54a656ef 444
6b691a5c 445long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
0f113f3e
MC
446{
447 int i;
d02b48c6 448
0f113f3e
MC
449 i = iarg;
450 return (BIO_ctrl(b, cmd, larg, (char *)&i));
451}
d02b48c6 452
417be660 453void *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
0f113f3e 454{
417be660 455 void *p = NULL;
58964a49 456
0f113f3e
MC
457 if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
458 return (NULL);
459 else
460 return (p);
461}
58964a49 462
95d29597 463long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
0f113f3e
MC
464{
465 long ret;
d02b48c6 466
0f113f3e 467 if (b == NULL)
98e553d2 468 return 0;
d02b48c6 469
0f113f3e
MC
470 if ((b->method == NULL) || (b->method->ctrl == NULL)) {
471 BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD);
98e553d2 472 return -2;
0f113f3e 473 }
d02b48c6 474
98e553d2
MC
475 if (b->callback != NULL || b->callback_ex != NULL) {
476 ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL);
477 if (ret <= 0)
478 return ret;
479 }
d02b48c6 480
0f113f3e 481 ret = b->method->ctrl(b, cmd, larg, parg);
d02b48c6 482
98e553d2
MC
483 if (b->callback != NULL || b->callback_ex != NULL)
484 ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd,
485 larg, ret, NULL);
486
487 return ret;
0f113f3e 488}
d02b48c6 489
0f113f3e
MC
490long BIO_callback_ctrl(BIO *b, int cmd,
491 void (*fp) (struct bio_st *, int, const char *, int,
492 long, long))
493{
494 long ret;
d3442bc7 495
0f113f3e
MC
496 if (b == NULL)
497 return (0);
d3442bc7 498
0f113f3e
MC
499 if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) {
500 BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD);
501 return (-2);
502 }
d3442bc7 503
98e553d2
MC
504 if (b->callback != NULL || b->callback_ex != NULL) {
505 ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, cmd, 0, 1L,
506 NULL);
507 if (ret <= 0)
508 return ret;
509 }
d3442bc7 510
0f113f3e 511 ret = b->method->callback_ctrl(b, cmd, fp);
d3442bc7 512
98e553d2
MC
513 if (b->callback != NULL || b->callback_ex != NULL)
514 ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, 0,
515 cmd, 0, ret, NULL);
516
517 return ret;
0f113f3e 518}
d3442bc7 519
0f113f3e
MC
520/*
521 * It is unfortunate to duplicate in functions what the BIO_(w)pending macros
95d29597 522 * do; but those macros have inappropriate return type, and for interfacing
0f113f3e
MC
523 * from other programming languages, C macros aren't much of a help anyway.
524 */
95d29597 525size_t BIO_ctrl_pending(BIO *bio)
0f113f3e
MC
526{
527 return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
528}
95d29597
BM
529
530size_t BIO_ctrl_wpending(BIO *bio)
0f113f3e
MC
531{
532 return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
533}
95d29597 534
d02b48c6 535/* put the 'bio' on the end of b's list of operators */
6b691a5c 536BIO *BIO_push(BIO *b, BIO *bio)
0f113f3e
MC
537{
538 BIO *lb;
539
540 if (b == NULL)
541 return (bio);
542 lb = b;
543 while (lb->next_bio != NULL)
544 lb = lb->next_bio;
545 lb->next_bio = bio;
546 if (bio != NULL)
547 bio->prev_bio = lb;
548 /* called to do internal processing */
549 BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
550 return (b);
551}
d02b48c6
RE
552
553/* Remove the first and return the rest */
6b691a5c 554BIO *BIO_pop(BIO *b)
0f113f3e
MC
555{
556 BIO *ret;
d02b48c6 557
0f113f3e
MC
558 if (b == NULL)
559 return (NULL);
560 ret = b->next_bio;
d02b48c6 561
0f113f3e 562 BIO_ctrl(b, BIO_CTRL_POP, 0, b);
5d780bab 563
0f113f3e
MC
564 if (b->prev_bio != NULL)
565 b->prev_bio->next_bio = b->next_bio;
566 if (b->next_bio != NULL)
567 b->next_bio->prev_bio = b->prev_bio;
d02b48c6 568
0f113f3e
MC
569 b->next_bio = NULL;
570 b->prev_bio = NULL;
571 return (ret);
572}
d02b48c6 573
6b691a5c 574BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
0f113f3e
MC
575{
576 BIO *b, *last;
577
578 b = last = bio;
579 for (;;) {
580 if (!BIO_should_retry(b))
581 break;
582 last = b;
583 b = b->next_bio;
584 if (b == NULL)
585 break;
586 }
587 if (reason != NULL)
588 *reason = last->retry_reason;
589 return (last);
590}
d02b48c6 591
6b691a5c 592int BIO_get_retry_reason(BIO *bio)
0f113f3e
MC
593{
594 return (bio->retry_reason);
595}
d02b48c6 596
a146ae55
MC
597void BIO_set_retry_reason(BIO *bio, int reason)
598{
599 bio->retry_reason = reason;
600}
601
6b691a5c 602BIO *BIO_find_type(BIO *bio, int type)
0f113f3e
MC
603{
604 int mt, mask;
605
cc99bfa7 606 if (bio == NULL)
0f113f3e
MC
607 return NULL;
608 mask = type & 0xff;
609 do {
610 if (bio->method != NULL) {
611 mt = bio->method->type;
612
613 if (!mask) {
614 if (mt & type)
615 return (bio);
616 } else if (mt == type)
617 return (bio);
618 }
619 bio = bio->next_bio;
620 } while (bio != NULL);
621 return (NULL);
622}
d02b48c6 623
cfd3bb17 624BIO *BIO_next(BIO *b)
0f113f3e 625{
cc99bfa7 626 if (b == NULL)
0f113f3e
MC
627 return NULL;
628 return b->next_bio;
629}
cfd3bb17 630
a146ae55
MC
631void BIO_set_next(BIO *b, BIO *next)
632{
633 b->next_bio = next;
634}
635
6b691a5c 636void BIO_free_all(BIO *bio)
0f113f3e
MC
637{
638 BIO *b;
639 int ref;
640
641 while (bio != NULL) {
642 b = bio;
643 ref = b->references;
644 bio = bio->next_bio;
645 BIO_free(b);
646 /* Since ref count > 1, don't free anyone else. */
647 if (ref > 1)
648 break;
649 }
650}
d02b48c6 651
6b691a5c 652BIO *BIO_dup_chain(BIO *in)
0f113f3e
MC
653{
654 BIO *ret = NULL, *eoc = NULL, *bio, *new_bio;
655
656 for (bio = in; bio != NULL; bio = bio->next_bio) {
657 if ((new_bio = BIO_new(bio->method)) == NULL)
658 goto err;
659 new_bio->callback = bio->callback;
98e553d2 660 new_bio->callback_ex = bio->callback_ex;
0f113f3e
MC
661 new_bio->cb_arg = bio->cb_arg;
662 new_bio->init = bio->init;
663 new_bio->shutdown = bio->shutdown;
664 new_bio->flags = bio->flags;
665
666 /* This will let SSL_s_sock() work with stdin/stdout */
667 new_bio->num = bio->num;
668
669 if (!BIO_dup_state(bio, (char *)new_bio)) {
670 BIO_free(new_bio);
671 goto err;
672 }
673
674 /* copy app data */
675 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data,
aec54108
MC
676 &bio->ex_data)) {
677 BIO_free(new_bio);
0f113f3e 678 goto err;
aec54108 679 }
0f113f3e
MC
680
681 if (ret == NULL) {
682 eoc = new_bio;
683 ret = eoc;
684 } else {
685 BIO_push(eoc, new_bio);
686 eoc = new_bio;
687 }
688 }
689 return (ret);
690 err:
aec54108
MC
691 BIO_free_all(ret);
692
0f113f3e
MC
693 return (NULL);
694}
d02b48c6 695
6b691a5c 696void BIO_copy_next_retry(BIO *b)
0f113f3e
MC
697{
698 BIO_set_flags(b, BIO_get_retry_flags(b->next_bio));
699 b->retry_reason = b->next_bio->retry_reason;
700}
d02b48c6 701
dd9d233e 702int BIO_set_ex_data(BIO *bio, int idx, void *data)
0f113f3e
MC
703{
704 return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data));
705}
58964a49 706
dd9d233e 707void *BIO_get_ex_data(BIO *bio, int idx)
0f113f3e
MC
708{
709 return (CRYPTO_get_ex_data(&(bio->ex_data), idx));
710}
58964a49 711
b8b12aad 712uint64_t BIO_number_read(BIO *bio)
c3ed3b6e 713{
0f113f3e
MC
714 if (bio)
715 return bio->num_read;
716 return 0;
c3ed3b6e
DSH
717}
718
b8b12aad 719uint64_t BIO_number_written(BIO *bio)
c3ed3b6e 720{
0f113f3e
MC
721 if (bio)
722 return bio->num_write;
723 return 0;
c3ed3b6e 724}
ff234405 725
1ee7b8b9
MC
726void bio_free_ex_data(BIO *bio)
727{
728 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
729}
ff234405
MC
730
731void bio_cleanup(void)
732{
733#ifndef OPENSSL_NO_SOCK
734 bio_sock_cleanup_int();
735 CRYPTO_THREAD_lock_free(bio_lookup_lock);
736 bio_lookup_lock = NULL;
5a7ad1f0 737#endif
8b8d963d
RS
738 CRYPTO_THREAD_lock_free(bio_type_lock);
739 bio_type_lock = NULL;
ff234405 740}