1/* $OpenBSD: bio_lib.c,v 1.53 2024/03/27 01:22:30 tb 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 <limits.h> 61#include <stdio.h> 62 63#include <openssl/bio.h> 64#include <openssl/crypto.h> 65#include <openssl/err.h> 66#include <openssl/stack.h> 67 68#include "bio_local.h" 69 70/* 71 * Helper function to work out whether to call the new style callback or the old 72 * one, and translate between the two. 73 * 74 * This has a long return type for consistency with the old callback. Similarly 75 * for the "long" used for "inret" 76 */ 77static long 78bio_call_callback(BIO *b, int oper, const char *argp, size_t len, int argi, 79 long argl, long inret, size_t *processed) 80{ 81 long ret; 82 int bareoper; 83 84 if (b->callback_ex != NULL) 85 return b->callback_ex(b, oper, argp, len, argi, argl, inret, 86 processed); 87 88 /* 89 * We have an old style callback, so we will have to do nasty casts and 90 * check for overflows. 91 */ 92 93 bareoper = oper & ~BIO_CB_RETURN; 94 95 if (bareoper == BIO_CB_READ || bareoper == BIO_CB_WRITE || 96 bareoper == BIO_CB_GETS) { 97 /* In this case len is set and should be used instead of argi. */ 98 if (len > INT_MAX) 99 return -1; 100 argi = (int)len; 101 } 102 103 if (inret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) { 104 if (*processed > INT_MAX) 105 return -1; 106 inret = *processed; 107 } 108 109 ret = b->callback(b, oper, argp, argi, argl, inret); 110 111 if (ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) { 112 *processed = (size_t)ret; 113 ret = 1; 114 } 115 116 return ret; 117} 118 119int 120BIO_get_new_index(void) 121{ 122 static int bio_type_index = BIO_TYPE_START; 123 int index; 124 125 /* The index will collide with the BIO flag bits if it exceeds 255. */ 126 index = CRYPTO_add(&bio_type_index, 1, CRYPTO_LOCK_BIO); 127 if (index > 255) 128 return -1; 129 130 return index; 131} 132LCRYPTO_ALIAS(BIO_get_new_index); 133 134BIO * 135BIO_new(const BIO_METHOD *method) 136{ 137 BIO *bio = NULL; 138 139 if ((bio = calloc(1, sizeof(BIO))) == NULL) { 140 BIOerror(ERR_R_MALLOC_FAILURE); 141 return NULL; 142 } 143 144 bio->method = method; 145 bio->shutdown = 1; 146 bio->references = 1; 147 148 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); 149 150 if (method->create != NULL) { 151 if (!method->create(bio)) { 152 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, 153 &bio->ex_data); 154 free(bio); 155 return NULL; 156 } 157 } 158 159 return bio; 160} 161LCRYPTO_ALIAS(BIO_new); 162 163int 164BIO_free(BIO *bio) 165{ 166 int ret; 167 168 if (bio == NULL) 169 return 0; 170 171 if (CRYPTO_add(&bio->references, -1, CRYPTO_LOCK_BIO) > 0) 172 return 1; 173 174 if (bio->callback != NULL || bio->callback_ex != NULL) { 175 if ((ret = (int)bio_call_callback(bio, BIO_CB_FREE, NULL, 0, 0, 176 0L, 1L, NULL)) <= 0) 177 return ret; 178 } 179 180 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); 181 182 if (bio->method != NULL && bio->method->destroy != NULL) 183 bio->method->destroy(bio); 184 185 free(bio); 186 187 return 1; 188} 189LCRYPTO_ALIAS(BIO_free); 190 191void 192BIO_vfree(BIO *bio) 193{ 194 BIO_free(bio); 195} 196LCRYPTO_ALIAS(BIO_vfree); 197 198int 199BIO_up_ref(BIO *bio) 200{ 201 return CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO) > 1; 202} 203LCRYPTO_ALIAS(BIO_up_ref); 204 205void * 206BIO_get_data(BIO *bio) 207{ 208 return bio->ptr; 209} 210LCRYPTO_ALIAS(BIO_get_data); 211 212void 213BIO_set_data(BIO *bio, void *ptr) 214{ 215 bio->ptr = ptr; 216} 217LCRYPTO_ALIAS(BIO_set_data); 218 219int 220BIO_get_init(BIO *bio) 221{ 222 return bio->init; 223} 224LCRYPTO_ALIAS(BIO_get_init); 225 226void 227BIO_set_init(BIO *bio, int init) 228{ 229 bio->init = init; 230} 231LCRYPTO_ALIAS(BIO_set_init); 232 233int 234BIO_get_shutdown(BIO *bio) 235{ 236 return bio->shutdown; 237} 238LCRYPTO_ALIAS(BIO_get_shutdown); 239 240void 241BIO_set_shutdown(BIO *bio, int shut) 242{ 243 bio->shutdown = shut; 244} 245LCRYPTO_ALIAS(BIO_set_shutdown); 246 247void 248BIO_clear_flags(BIO *bio, int flags) 249{ 250 bio->flags &= ~flags; 251} 252LCRYPTO_ALIAS(BIO_clear_flags); 253 254int 255BIO_test_flags(const BIO *bio, int flags) 256{ 257 return (bio->flags & flags); 258} 259LCRYPTO_ALIAS(BIO_test_flags); 260 261void 262BIO_set_flags(BIO *bio, int flags) 263{ 264 bio->flags |= flags; 265} 266LCRYPTO_ALIAS(BIO_set_flags); 267 268BIO_callback_fn 269BIO_get_callback(const BIO *bio) 270{ 271 return bio->callback; 272} 273LCRYPTO_ALIAS(BIO_get_callback); 274 275void 276BIO_set_callback(BIO *bio, BIO_callback_fn cb) 277{ 278 bio->callback = cb; 279} 280LCRYPTO_ALIAS(BIO_set_callback); 281 282BIO_callback_fn_ex 283BIO_get_callback_ex(const BIO *bio) 284{ 285 return bio->callback_ex; 286} 287LCRYPTO_ALIAS(BIO_get_callback_ex); 288 289void 290BIO_set_callback_ex(BIO *bio, BIO_callback_fn_ex cb) 291{ 292 bio->callback_ex = cb; 293} 294LCRYPTO_ALIAS(BIO_set_callback_ex); 295 296void 297BIO_set_callback_arg(BIO *bio, char *arg) 298{ 299 bio->cb_arg = arg; 300} 301LCRYPTO_ALIAS(BIO_set_callback_arg); 302 303char * 304BIO_get_callback_arg(const BIO *bio) 305{ 306 return bio->cb_arg; 307} 308LCRYPTO_ALIAS(BIO_get_callback_arg); 309 310const char * 311BIO_method_name(const BIO *bio) 312{ 313 return bio->method->name; 314} 315LCRYPTO_ALIAS(BIO_method_name); 316 317int 318BIO_method_type(const BIO *bio) 319{ 320 return bio->method->type; 321} 322LCRYPTO_ALIAS(BIO_method_type); 323 324int 325BIO_read(BIO *b, void *out, int outl) 326{ 327 size_t readbytes = 0; 328 int ret; 329 330 if (b == NULL) { 331 BIOerror(ERR_R_PASSED_NULL_PARAMETER); 332 return (-1); 333 } 334 335 if (outl <= 0) 336 return (0); 337 338 if (out == NULL) { 339 BIOerror(ERR_R_PASSED_NULL_PARAMETER); 340 return (-1); 341 } 342 343 if (b->method == NULL || b->method->bread == NULL) { 344 BIOerror(BIO_R_UNSUPPORTED_METHOD); 345 return (-2); 346 } 347 348 if (b->callback != NULL || b->callback_ex != NULL) { 349 if ((ret = (int)bio_call_callback(b, BIO_CB_READ, out, outl, 0, 350 0L, 1L, NULL)) <= 0) 351 return (ret); 352 } 353 354 if (!b->init) { 355 BIOerror(BIO_R_UNINITIALIZED); 356 return (-2); 357 } 358 359 if ((ret = b->method->bread(b, out, outl)) > 0) 360 readbytes = (size_t)ret; 361 362 b->num_read += readbytes; 363 364 if (b->callback != NULL || b->callback_ex != NULL) { 365 ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, 366 out, outl, 0, 0L, (ret > 0) ? 1 : ret, &readbytes); 367 } 368 369 if (ret > 0) { 370 if (readbytes > INT_MAX) { 371 BIOerror(BIO_R_LENGTH_TOO_LONG); 372 ret = -1; 373 } else { 374 ret = (int)readbytes; 375 } 376 } 377 378 return (ret); 379} 380LCRYPTO_ALIAS(BIO_read); 381 382int 383BIO_write(BIO *b, const void *in, int inl) 384{ 385 size_t writebytes = 0; 386 int ret; 387 388 /* Not an error. Things like SMIME_text() assume that this succeeds. */ 389 if (b == NULL) 390 return (0); 391 392 if (inl <= 0) 393 return (0); 394 395 if (in == NULL) { 396 BIOerror(ERR_R_PASSED_NULL_PARAMETER); 397 return (-1); 398 } 399 400 if (b->method == NULL || b->method->bwrite == NULL) { 401 BIOerror(BIO_R_UNSUPPORTED_METHOD); 402 return (-2); 403 } 404 405 if (b->callback != NULL || b->callback_ex != NULL) { 406 if ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, in, inl, 0, 407 0L, 1L, NULL)) <= 0) 408 return (ret); 409 } 410 411 if (!b->init) { 412 BIOerror(BIO_R_UNINITIALIZED); 413 return (-2); 414 } 415 416 if ((ret = b->method->bwrite(b, in, inl)) > 0) 417 writebytes = ret; 418 419 b->num_write += writebytes; 420 421 if (b->callback != NULL || b->callback_ex != NULL) { 422 ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, 423 in, inl, 0, 0L, (ret > 0) ? 1 : ret, &writebytes); 424 } 425 426 if (ret > 0) { 427 if (writebytes > INT_MAX) { 428 BIOerror(BIO_R_LENGTH_TOO_LONG); 429 ret = -1; 430 } else { 431 ret = (int)writebytes; 432 } 433 } 434 435 return (ret); 436} 437LCRYPTO_ALIAS(BIO_write); 438 439int 440BIO_puts(BIO *b, const char *in) 441{ 442 size_t writebytes = 0; 443 int ret; 444 445 if (b == NULL || b->method == NULL || b->method->bputs == NULL) { 446 BIOerror(BIO_R_UNSUPPORTED_METHOD); 447 return (-2); 448 } 449 450 if (b->callback != NULL || b->callback_ex != NULL) { 451 if ((ret = (int)bio_call_callback(b, BIO_CB_PUTS, in, 0, 0, 0L, 452 1L, NULL)) <= 0) 453 return (ret); 454 } 455 456 if (!b->init) { 457 BIOerror(BIO_R_UNINITIALIZED); 458 return (-2); 459 } 460 461 if ((ret = b->method->bputs(b, in)) > 0) 462 writebytes = ret; 463 464 b->num_write += writebytes; 465 466 if (b->callback != NULL || b->callback_ex != NULL) { 467 ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, 468 in, 0, 0, 0L, (ret > 0) ? 1 : ret, &writebytes); 469 } 470 471 if (ret > 0) { 472 if (writebytes > INT_MAX) { 473 BIOerror(BIO_R_LENGTH_TOO_LONG); 474 ret = -1; 475 } else { 476 ret = (int)writebytes; 477 } 478 } 479 480 return (ret); 481} 482LCRYPTO_ALIAS(BIO_puts); 483 484int 485BIO_gets(BIO *b, char *in, int inl) 486{ 487 size_t readbytes = 0; 488 int ret; 489 490 if (b == NULL || b->method == NULL || b->method->bgets == NULL) { 491 BIOerror(BIO_R_UNSUPPORTED_METHOD); 492 return (-2); 493 } 494 495 if (b->callback != NULL || b->callback_ex != NULL) { 496 if ((ret = (int)bio_call_callback(b, BIO_CB_GETS, in, inl, 0, 0L, 497 1, NULL)) <= 0) 498 return (ret); 499 } 500 501 if (!b->init) { 502 BIOerror(BIO_R_UNINITIALIZED); 503 return (-2); 504 } 505 506 if ((ret = b->method->bgets(b, in, inl)) > 0) 507 readbytes = ret; 508 509 if (b->callback != NULL || b->callback_ex != NULL) { 510 ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, in, 511 inl, 0, 0L, (ret > 0) ? 1 : ret, &readbytes); 512 } 513 514 if (ret > 0) { 515 if (readbytes > INT_MAX) { 516 BIOerror(BIO_R_LENGTH_TOO_LONG); 517 ret = -1; 518 } else { 519 ret = (int)readbytes; 520 } 521 } 522 523 return (ret); 524} 525LCRYPTO_ALIAS(BIO_gets); 526 527int 528BIO_indent(BIO *bio, int indent, int max) 529{ 530 if (indent > max) 531 indent = max; 532 if (indent <= 0) 533 return 1; 534 if (BIO_printf(bio, "%*s", indent, "") <= 0) 535 return 0; 536 return 1; 537} 538LCRYPTO_ALIAS(BIO_indent); 539 540long 541BIO_int_ctrl(BIO *bio, int cmd, long larg, int iarg) 542{ 543 int i; 544 545 i = iarg; 546 return BIO_ctrl(bio, cmd, larg, (char *)&i); 547} 548LCRYPTO_ALIAS(BIO_int_ctrl); 549 550char * 551BIO_ptr_ctrl(BIO *bio, int cmd, long larg) 552{ 553 char *p = NULL; 554 555 if (BIO_ctrl(bio, cmd, larg, (char *)&p) <= 0) 556 return NULL; 557 else 558 return p; 559} 560LCRYPTO_ALIAS(BIO_ptr_ctrl); 561 562long 563BIO_ctrl(BIO *b, int cmd, long larg, void *parg) 564{ 565 long ret; 566 567 if (b == NULL) 568 return (0); 569 570 if (b->method == NULL || b->method->ctrl == NULL) { 571 BIOerror(BIO_R_UNSUPPORTED_METHOD); 572 return (-2); 573 } 574 575 if (b->callback != NULL || b->callback_ex != NULL) { 576 if ((ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 577 1L, NULL)) <= 0) 578 return (ret); 579 } 580 581 ret = b->method->ctrl(b, cmd, larg, parg); 582 583 if (b->callback != NULL || b->callback_ex != NULL) { 584 ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, 585 cmd, larg, ret, NULL); 586 } 587 588 return (ret); 589} 590LCRYPTO_ALIAS(BIO_ctrl); 591 592long 593BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) 594{ 595 long ret; 596 597 if (b == NULL) 598 return (0); 599 600 if (b->method == NULL || b->method->callback_ctrl == NULL || 601 cmd != BIO_CTRL_SET_CALLBACK) { 602 BIOerror(BIO_R_UNSUPPORTED_METHOD); 603 return (-2); 604 } 605 606 if (b->callback != NULL || b->callback_ex != NULL) { 607 if ((ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, 608 cmd, 0, 1L, NULL)) <= 0) 609 return (ret); 610 } 611 612 ret = b->method->callback_ctrl(b, cmd, fp); 613 614 if (b->callback != NULL || b->callback_ex != NULL) { 615 ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, 616 (void *)&fp, 0, cmd, 0, ret, NULL); 617 } 618 619 return (ret); 620} 621LCRYPTO_ALIAS(BIO_callback_ctrl); 622 623/* It is unfortunate to duplicate in functions what the BIO_(w)pending macros 624 * do; but those macros have inappropriate return type, and for interfacing 625 * from other programming languages, C macros aren't much of a help anyway. */ 626size_t 627BIO_ctrl_pending(BIO *bio) 628{ 629 return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); 630} 631LCRYPTO_ALIAS(BIO_ctrl_pending); 632 633size_t 634BIO_ctrl_wpending(BIO *bio) 635{ 636 return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); 637} 638LCRYPTO_ALIAS(BIO_ctrl_wpending); 639 640 641/* 642 * Append "bio" to the end of the chain containing "b": 643 * Two chains "b -> lb" and "oldhead -> bio" 644 * become two chains "b -> lb -> bio" and "oldhead". 645 */ 646BIO * 647BIO_push(BIO *b, BIO *bio) 648{ 649 BIO *lb; 650 651 if (b == NULL) 652 return (bio); 653 lb = b; 654 while (lb->next_bio != NULL) 655 lb = lb->next_bio; 656 lb->next_bio = bio; 657 if (bio != NULL) { 658 if (bio->prev_bio != NULL) 659 bio->prev_bio->next_bio = NULL; 660 bio->prev_bio = lb; 661 } 662 /* called to do internal processing */ 663 BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb); 664 return (b); 665} 666LCRYPTO_ALIAS(BIO_push); 667 668/* Remove the first and return the rest */ 669BIO * 670BIO_pop(BIO *b) 671{ 672 BIO *ret; 673 674 if (b == NULL) 675 return (NULL); 676 ret = b->next_bio; 677 678 BIO_ctrl(b, BIO_CTRL_POP, 0, b); 679 680 if (b->prev_bio != NULL) 681 b->prev_bio->next_bio = b->next_bio; 682 if (b->next_bio != NULL) 683 b->next_bio->prev_bio = b->prev_bio; 684 685 b->next_bio = NULL; 686 b->prev_bio = NULL; 687 return (ret); 688} 689LCRYPTO_ALIAS(BIO_pop); 690 691BIO * 692BIO_get_retry_BIO(BIO *bio, int *reason) 693{ 694 BIO *b, *last; 695 696 b = last = bio; 697 for (;;) { 698 if (!BIO_should_retry(b)) 699 break; 700 last = b; 701 b = b->next_bio; 702 if (b == NULL) 703 break; 704 } 705 if (reason != NULL) 706 *reason = last->retry_reason; 707 return (last); 708} 709LCRYPTO_ALIAS(BIO_get_retry_BIO); 710 711int 712BIO_get_retry_reason(BIO *bio) 713{ 714 return bio->retry_reason; 715} 716LCRYPTO_ALIAS(BIO_get_retry_reason); 717 718void 719BIO_set_retry_reason(BIO *bio, int reason) 720{ 721 bio->retry_reason = reason; 722} 723LCRYPTO_ALIAS(BIO_set_retry_reason); 724 725BIO * 726BIO_find_type(BIO *bio, int type) 727{ 728 int mt, mask; 729 730 if (!bio) 731 return NULL; 732 mask = type & 0xff; 733 do { 734 if (bio->method != NULL) { 735 mt = bio->method->type; 736 if (!mask) { 737 if (mt & type) 738 return (bio); 739 } else if (mt == type) 740 return (bio); 741 } 742 bio = bio->next_bio; 743 } while (bio != NULL); 744 return (NULL); 745} 746LCRYPTO_ALIAS(BIO_find_type); 747 748BIO * 749BIO_next(BIO *b) 750{ 751 if (!b) 752 return NULL; 753 return b->next_bio; 754} 755LCRYPTO_ALIAS(BIO_next); 756 757/* 758 * Two chains "bio -> oldtail" and "oldhead -> next" become 759 * three chains "oldtail", "bio -> next", and "oldhead". 760 */ 761void 762BIO_set_next(BIO *bio, BIO *next) 763{ 764 /* Cut off the tail of the chain containing bio after bio. */ 765 if (bio->next_bio != NULL) 766 bio->next_bio->prev_bio = NULL; 767 768 /* Cut off the head of the chain containing next before next. */ 769 if (next != NULL && next->prev_bio != NULL) 770 next->prev_bio->next_bio = NULL; 771 772 /* Append the chain starting at next to the chain ending at bio. */ 773 bio->next_bio = next; 774 if (next != NULL) 775 next->prev_bio = bio; 776} 777LCRYPTO_ALIAS(BIO_set_next); 778 779void 780BIO_free_all(BIO *bio) 781{ 782 BIO *b; 783 int ref; 784 785 while (bio != NULL) { 786 b = bio; 787 ref = b->references; 788 bio = bio->next_bio; 789 BIO_free(b); 790 /* Since ref count > 1, don't free anyone else. */ 791 if (ref > 1) 792 break; 793 } 794} 795LCRYPTO_ALIAS(BIO_free_all); 796 797BIO * 798BIO_dup_chain(BIO *in) 799{ 800 BIO *new_chain = NULL, *new_bio = NULL, *tail = NULL; 801 BIO *bio; 802 803 for (bio = in; bio != NULL; bio = bio->next_bio) { 804 if ((new_bio = BIO_new(bio->method)) == NULL) 805 goto err; 806 new_bio->callback = bio->callback; 807 new_bio->callback_ex = bio->callback_ex; 808 new_bio->cb_arg = bio->cb_arg; 809 new_bio->init = bio->init; 810 new_bio->shutdown = bio->shutdown; 811 new_bio->flags = bio->flags; 812 new_bio->num = bio->num; 813 814 if (!BIO_dup_state(bio, new_bio)) 815 goto err; 816 817 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, 818 &new_bio->ex_data, &bio->ex_data)) 819 goto err; 820 821 if (BIO_push(tail, new_bio) == NULL) 822 goto err; 823 824 tail = new_bio; 825 if (new_chain == NULL) 826 new_chain = new_bio; 827 } 828 829 return new_chain; 830 831 err: 832 BIO_free(new_bio); 833 BIO_free_all(new_chain); 834 835 return NULL; 836} 837LCRYPTO_ALIAS(BIO_dup_chain); 838 839void 840BIO_copy_next_retry(BIO *b) 841{ 842 BIO_set_flags(b, BIO_get_retry_flags(b->next_bio)); 843 b->retry_reason = b->next_bio->retry_reason; 844} 845LCRYPTO_ALIAS(BIO_copy_next_retry); 846 847int 848BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 849 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 850{ 851 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp, 852 new_func, dup_func, free_func); 853} 854 855int 856BIO_set_ex_data(BIO *bio, int idx, void *data) 857{ 858 return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data)); 859} 860LCRYPTO_ALIAS(BIO_set_ex_data); 861 862void * 863BIO_get_ex_data(BIO *bio, int idx) 864{ 865 return (CRYPTO_get_ex_data(&(bio->ex_data), idx)); 866} 867LCRYPTO_ALIAS(BIO_get_ex_data); 868 869unsigned long 870BIO_number_read(BIO *bio) 871{ 872 if (bio) 873 return bio->num_read; 874 return 0; 875} 876LCRYPTO_ALIAS(BIO_number_read); 877 878unsigned long 879BIO_number_written(BIO *bio) 880{ 881 if (bio) 882 return bio->num_write; 883 return 0; 884} 885LCRYPTO_ALIAS(BIO_number_written); 886