1 /* $OpenBSD: bio_lib.c,v 1.54 2024/07/09 06:14:59 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 <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 */ 77 static long 78 bio_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 119 int 120 BIO_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 } 132 LCRYPTO_ALIAS(BIO_get_new_index); 133 134 BIO * 135 BIO_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 } 161 LCRYPTO_ALIAS(BIO_new); 162 163 int 164 BIO_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 } 189 LCRYPTO_ALIAS(BIO_free); 190 191 void 192 BIO_vfree(BIO *bio) 193 { 194 BIO_free(bio); 195 } 196 LCRYPTO_ALIAS(BIO_vfree); 197 198 int 199 BIO_up_ref(BIO *bio) 200 { 201 return CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO) > 1; 202 } 203 LCRYPTO_ALIAS(BIO_up_ref); 204 205 void * 206 BIO_get_data(BIO *bio) 207 { 208 return bio->ptr; 209 } 210 LCRYPTO_ALIAS(BIO_get_data); 211 212 void 213 BIO_set_data(BIO *bio, void *ptr) 214 { 215 bio->ptr = ptr; 216 } 217 LCRYPTO_ALIAS(BIO_set_data); 218 219 int 220 BIO_get_init(BIO *bio) 221 { 222 return bio->init; 223 } 224 LCRYPTO_ALIAS(BIO_get_init); 225 226 void 227 BIO_set_init(BIO *bio, int init) 228 { 229 bio->init = init; 230 } 231 LCRYPTO_ALIAS(BIO_set_init); 232 233 int 234 BIO_get_shutdown(BIO *bio) 235 { 236 return bio->shutdown; 237 } 238 LCRYPTO_ALIAS(BIO_get_shutdown); 239 240 void 241 BIO_set_shutdown(BIO *bio, int shut) 242 { 243 bio->shutdown = shut; 244 } 245 LCRYPTO_ALIAS(BIO_set_shutdown); 246 247 void 248 BIO_clear_flags(BIO *bio, int flags) 249 { 250 bio->flags &= ~flags; 251 } 252 LCRYPTO_ALIAS(BIO_clear_flags); 253 254 int 255 BIO_test_flags(const BIO *bio, int flags) 256 { 257 return (bio->flags & flags); 258 } 259 LCRYPTO_ALIAS(BIO_test_flags); 260 261 void 262 BIO_set_flags(BIO *bio, int flags) 263 { 264 bio->flags |= flags; 265 } 266 LCRYPTO_ALIAS(BIO_set_flags); 267 268 BIO_callback_fn 269 BIO_get_callback(const BIO *bio) 270 { 271 return bio->callback; 272 } 273 LCRYPTO_ALIAS(BIO_get_callback); 274 275 void 276 BIO_set_callback(BIO *bio, BIO_callback_fn cb) 277 { 278 bio->callback = cb; 279 } 280 LCRYPTO_ALIAS(BIO_set_callback); 281 282 BIO_callback_fn_ex 283 BIO_get_callback_ex(const BIO *bio) 284 { 285 return bio->callback_ex; 286 } 287 LCRYPTO_ALIAS(BIO_get_callback_ex); 288 289 void 290 BIO_set_callback_ex(BIO *bio, BIO_callback_fn_ex cb) 291 { 292 bio->callback_ex = cb; 293 } 294 LCRYPTO_ALIAS(BIO_set_callback_ex); 295 296 void 297 BIO_set_callback_arg(BIO *bio, char *arg) 298 { 299 bio->cb_arg = arg; 300 } 301 LCRYPTO_ALIAS(BIO_set_callback_arg); 302 303 char * 304 BIO_get_callback_arg(const BIO *bio) 305 { 306 return bio->cb_arg; 307 } 308 LCRYPTO_ALIAS(BIO_get_callback_arg); 309 310 const char * 311 BIO_method_name(const BIO *bio) 312 { 313 return bio->method->name; 314 } 315 LCRYPTO_ALIAS(BIO_method_name); 316 317 int 318 BIO_method_type(const BIO *bio) 319 { 320 return bio->method->type; 321 } 322 LCRYPTO_ALIAS(BIO_method_type); 323 324 int 325 BIO_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 } 380 LCRYPTO_ALIAS(BIO_read); 381 382 int 383 BIO_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 } 437 LCRYPTO_ALIAS(BIO_write); 438 439 int 440 BIO_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 } 482 LCRYPTO_ALIAS(BIO_puts); 483 484 int 485 BIO_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 } 525 LCRYPTO_ALIAS(BIO_gets); 526 527 int 528 BIO_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 } 538 LCRYPTO_ALIAS(BIO_indent); 539 540 long 541 BIO_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 } 548 LCRYPTO_ALIAS(BIO_int_ctrl); 549 550 char * 551 BIO_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 } 560 LCRYPTO_ALIAS(BIO_ptr_ctrl); 561 562 long 563 BIO_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 } 590 LCRYPTO_ALIAS(BIO_ctrl); 591 592 long 593 BIO_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 } 621 LCRYPTO_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. */ 626 size_t 627 BIO_ctrl_pending(BIO *bio) 628 { 629 return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); 630 } 631 LCRYPTO_ALIAS(BIO_ctrl_pending); 632 633 size_t 634 BIO_ctrl_wpending(BIO *bio) 635 { 636 return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); 637 } 638 LCRYPTO_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 */ 646 BIO * 647 BIO_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 } 666 LCRYPTO_ALIAS(BIO_push); 667 668 /* Remove the first and return the rest */ 669 BIO * 670 BIO_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 } 689 LCRYPTO_ALIAS(BIO_pop); 690 691 BIO * 692 BIO_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 } 709 LCRYPTO_ALIAS(BIO_get_retry_BIO); 710 711 int 712 BIO_get_retry_reason(BIO *bio) 713 { 714 return bio->retry_reason; 715 } 716 LCRYPTO_ALIAS(BIO_get_retry_reason); 717 718 void 719 BIO_set_retry_reason(BIO *bio, int reason) 720 { 721 bio->retry_reason = reason; 722 } 723 LCRYPTO_ALIAS(BIO_set_retry_reason); 724 725 BIO * 726 BIO_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 } 746 LCRYPTO_ALIAS(BIO_find_type); 747 748 BIO * 749 BIO_next(BIO *b) 750 { 751 if (!b) 752 return NULL; 753 return b->next_bio; 754 } 755 LCRYPTO_ALIAS(BIO_next); 756 757 /* 758 * Two chains "bio -> oldtail" and "oldhead -> next" become 759 * three chains "oldtail", "bio -> next", and "oldhead". 760 */ 761 void 762 BIO_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 } 777 LCRYPTO_ALIAS(BIO_set_next); 778 779 void 780 BIO_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 } 795 LCRYPTO_ALIAS(BIO_free_all); 796 797 BIO * 798 BIO_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 } 837 LCRYPTO_ALIAS(BIO_dup_chain); 838 839 void 840 BIO_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 } 845 LCRYPTO_ALIAS(BIO_copy_next_retry); 846 847 int 848 BIO_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 LCRYPTO_ALIAS(BIO_get_ex_new_index); 855 856 int 857 BIO_set_ex_data(BIO *bio, int idx, void *data) 858 { 859 return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data)); 860 } 861 LCRYPTO_ALIAS(BIO_set_ex_data); 862 863 void * 864 BIO_get_ex_data(BIO *bio, int idx) 865 { 866 return (CRYPTO_get_ex_data(&(bio->ex_data), idx)); 867 } 868 LCRYPTO_ALIAS(BIO_get_ex_data); 869 870 unsigned long 871 BIO_number_read(BIO *bio) 872 { 873 if (bio) 874 return bio->num_read; 875 return 0; 876 } 877 LCRYPTO_ALIAS(BIO_number_read); 878 879 unsigned long 880 BIO_number_written(BIO *bio) 881 { 882 if (bio) 883 return bio->num_write; 884 return 0; 885 } 886 LCRYPTO_ALIAS(BIO_number_written); 887