1 /* $OpenBSD: bio_lib.c,v 1.31 2021/12/09 15:28:58 schwarze 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 int 68 BIO_get_new_index(void) 69 { 70 static int bio_type_index = BIO_TYPE_START; 71 int index; 72 73 /* The index will collide with the BIO flag bits if it exceeds 255. */ 74 index = CRYPTO_add(&bio_type_index, 1, CRYPTO_LOCK_BIO); 75 if (index > 255) 76 return -1; 77 78 return index; 79 } 80 81 BIO * 82 BIO_new(const BIO_METHOD *method) 83 { 84 BIO *ret = NULL; 85 86 ret = malloc(sizeof(BIO)); 87 if (ret == NULL) { 88 BIOerror(ERR_R_MALLOC_FAILURE); 89 return (NULL); 90 } 91 if (!BIO_set(ret, method)) { 92 free(ret); 93 ret = NULL; 94 } 95 return (ret); 96 } 97 98 int 99 BIO_set(BIO *bio, const BIO_METHOD *method) 100 { 101 bio->method = method; 102 bio->callback = NULL; 103 bio->cb_arg = NULL; 104 bio->init = 0; 105 bio->shutdown = 1; 106 bio->flags = 0; 107 bio->retry_reason = 0; 108 bio->num = 0; 109 bio->ptr = NULL; 110 bio->prev_bio = NULL; 111 bio->next_bio = NULL; 112 bio->references = 1; 113 bio->num_read = 0L; 114 bio->num_write = 0L; 115 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); 116 if (method->create != NULL) 117 if (!method->create(bio)) { 118 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, 119 &bio->ex_data); 120 return (0); 121 } 122 return (1); 123 } 124 125 int 126 BIO_free(BIO *a) 127 { 128 int i; 129 130 if (a == NULL) 131 return (0); 132 133 i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO); 134 if (i > 0) 135 return (1); 136 if ((a->callback != NULL) && 137 ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0)) 138 return (i); 139 140 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); 141 142 if (a->method != NULL && a->method->destroy != NULL) 143 a->method->destroy(a); 144 free(a); 145 return (1); 146 } 147 148 void 149 BIO_vfree(BIO *a) 150 { 151 BIO_free(a); 152 } 153 154 int 155 BIO_up_ref(BIO *bio) 156 { 157 int refs = CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO); 158 return (refs > 1) ? 1 : 0; 159 } 160 161 void * 162 BIO_get_data(BIO *a) 163 { 164 return (a->ptr); 165 } 166 167 void 168 BIO_set_data(BIO *a, void *ptr) 169 { 170 a->ptr = ptr; 171 } 172 173 int 174 BIO_get_init(BIO *a) 175 { 176 return a->init; 177 } 178 179 void 180 BIO_set_init(BIO *a, int init) 181 { 182 a->init = init; 183 } 184 185 int 186 BIO_get_shutdown(BIO *a) 187 { 188 return (a->shutdown); 189 } 190 191 void 192 BIO_set_shutdown(BIO *a, int shut) 193 { 194 a->shutdown = shut; 195 } 196 197 void 198 BIO_clear_flags(BIO *b, int flags) 199 { 200 b->flags &= ~flags; 201 } 202 203 int 204 BIO_test_flags(const BIO *b, int flags) 205 { 206 return (b->flags & flags); 207 } 208 209 void 210 BIO_set_flags(BIO *b, int flags) 211 { 212 b->flags |= flags; 213 } 214 215 long 216 (*BIO_get_callback(const BIO *b))(struct bio_st *, int, const char *, int, 217 long, long) 218 { 219 return b->callback; 220 } 221 222 void 223 BIO_set_callback(BIO *b, long (*cb)(struct bio_st *, int, const char *, int, 224 long, long)) 225 { 226 b->callback = cb; 227 } 228 229 void 230 BIO_set_callback_arg(BIO *b, char *arg) 231 { 232 b->cb_arg = arg; 233 } 234 235 char * 236 BIO_get_callback_arg(const BIO *b) 237 { 238 return b->cb_arg; 239 } 240 241 const char * 242 BIO_method_name(const BIO *b) 243 { 244 return b->method->name; 245 } 246 247 int 248 BIO_method_type(const BIO *b) 249 { 250 return b->method->type; 251 } 252 253 int 254 BIO_read(BIO *b, void *out, int outl) 255 { 256 int i; 257 long (*cb)(BIO *, int, const char *, int, long, long); 258 259 if (b == NULL) 260 return (0); 261 262 if (out == NULL || outl <= 0) 263 return (0); 264 265 if (b->method == NULL || b->method->bread == NULL) { 266 BIOerror(BIO_R_UNSUPPORTED_METHOD); 267 return (-2); 268 } 269 270 cb = b->callback; 271 if ((cb != NULL) && 272 ((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0)) 273 return (i); 274 275 if (!b->init) { 276 BIOerror(BIO_R_UNINITIALIZED); 277 return (-2); 278 } 279 280 i = b->method->bread(b, out, outl); 281 282 if (i > 0) 283 b->num_read += (unsigned long)i; 284 285 if (cb != NULL) 286 i = (int)cb(b, BIO_CB_READ|BIO_CB_RETURN, out, outl, 287 0L, (long)i); 288 289 return (i); 290 } 291 292 int 293 BIO_write(BIO *b, const void *in, int inl) 294 { 295 int i; 296 long (*cb)(BIO *, int, const char *, int, long, long); 297 298 if (b == NULL) 299 return (0); 300 301 if (in == NULL || inl <= 0) 302 return (0); 303 304 if (b->method == NULL || b->method->bwrite == NULL) { 305 BIOerror(BIO_R_UNSUPPORTED_METHOD); 306 return (-2); 307 } 308 309 cb = b->callback; 310 if ((cb != NULL) && 311 ((i = (int)cb(b, BIO_CB_WRITE, in, inl, 0L, 1L)) <= 0)) 312 return (i); 313 314 if (!b->init) { 315 BIOerror(BIO_R_UNINITIALIZED); 316 return (-2); 317 } 318 319 i = b->method->bwrite(b, in, inl); 320 321 if (i > 0) 322 b->num_write += (unsigned long)i; 323 324 if (cb != NULL) 325 i = (int)cb(b, BIO_CB_WRITE|BIO_CB_RETURN, in, inl, 326 0L, (long)i); 327 return (i); 328 } 329 330 int 331 BIO_puts(BIO *b, const char *in) 332 { 333 int i; 334 long (*cb)(BIO *, int, const char *, int, long, long); 335 336 if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) { 337 BIOerror(BIO_R_UNSUPPORTED_METHOD); 338 return (-2); 339 } 340 341 cb = b->callback; 342 343 if ((cb != NULL) && 344 ((i = (int)cb(b, BIO_CB_PUTS, in, 0, 0L, 1L)) <= 0)) 345 return (i); 346 347 if (!b->init) { 348 BIOerror(BIO_R_UNINITIALIZED); 349 return (-2); 350 } 351 352 i = b->method->bputs(b, in); 353 354 if (i > 0) 355 b->num_write += (unsigned long)i; 356 357 if (cb != NULL) 358 i = (int)cb(b, BIO_CB_PUTS|BIO_CB_RETURN, in, 0, 0L, (long)i); 359 return (i); 360 } 361 362 int 363 BIO_gets(BIO *b, char *in, int inl) 364 { 365 int i; 366 long (*cb)(BIO *, int, const char *, int, long, long); 367 368 if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) { 369 BIOerror(BIO_R_UNSUPPORTED_METHOD); 370 return (-2); 371 } 372 373 cb = b->callback; 374 375 if ((cb != NULL) && 376 ((i = (int)cb(b, BIO_CB_GETS, in, inl, 0L, 1L)) <= 0)) 377 return (i); 378 379 if (!b->init) { 380 BIOerror(BIO_R_UNINITIALIZED); 381 return (-2); 382 } 383 384 i = b->method->bgets(b, in, inl); 385 386 if (cb != NULL) 387 i = (int)cb(b, BIO_CB_GETS|BIO_CB_RETURN, in, inl, 0L, (long)i); 388 return (i); 389 } 390 391 int 392 BIO_indent(BIO *b, int indent, int max) 393 { 394 if (indent > max) 395 indent = max; 396 if (indent < 0) 397 indent = 0; 398 while (indent--) 399 if (BIO_puts(b, " ") != 1) 400 return 0; 401 return 1; 402 } 403 404 long 405 BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) 406 { 407 int i; 408 409 i = iarg; 410 return (BIO_ctrl(b, cmd, larg, (char *)&i)); 411 } 412 413 char * 414 BIO_ptr_ctrl(BIO *b, int cmd, long larg) 415 { 416 char *p = NULL; 417 418 if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0) 419 return (NULL); 420 else 421 return (p); 422 } 423 424 long 425 BIO_ctrl(BIO *b, int cmd, long larg, void *parg) 426 { 427 long ret; 428 long (*cb)(BIO *, int, const char *, int, long, long); 429 430 if (b == NULL) 431 return (0); 432 433 if ((b->method == NULL) || (b->method->ctrl == NULL)) { 434 BIOerror(BIO_R_UNSUPPORTED_METHOD); 435 return (-2); 436 } 437 438 cb = b->callback; 439 440 if ((cb != NULL) && 441 ((ret = cb(b, BIO_CB_CTRL, parg, cmd, larg, 1L)) <= 0)) 442 return (ret); 443 444 ret = b->method->ctrl(b, cmd, larg, parg); 445 446 if (cb != NULL) 447 ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, parg, cmd, larg, ret); 448 return (ret); 449 } 450 451 long 452 BIO_callback_ctrl(BIO *b, int cmd, 453 void (*fp)(struct bio_st *, int, const char *, int, long, long)) 454 { 455 long ret; 456 long (*cb)(BIO *, int, const char *, int, long, long); 457 458 if (b == NULL) 459 return (0); 460 461 if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) { 462 BIOerror(BIO_R_UNSUPPORTED_METHOD); 463 return (-2); 464 } 465 466 cb = b->callback; 467 468 if ((cb != NULL) && 469 ((ret = cb(b, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L)) <= 0)) 470 return (ret); 471 472 ret = b->method->callback_ctrl(b, cmd, fp); 473 474 if (cb != NULL) 475 ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, (void *)&fp, cmd, 0, ret); 476 return (ret); 477 } 478 479 /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros 480 * do; but those macros have inappropriate return type, and for interfacing 481 * from other programming languages, C macros aren't much of a help anyway. */ 482 size_t 483 BIO_ctrl_pending(BIO *bio) 484 { 485 return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); 486 } 487 488 size_t 489 BIO_ctrl_wpending(BIO *bio) 490 { 491 return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); 492 } 493 494 495 /* put the 'bio' on the end of b's list of operators */ 496 BIO * 497 BIO_push(BIO *b, BIO *bio) 498 { 499 BIO *lb; 500 501 if (b == NULL) 502 return (bio); 503 lb = b; 504 while (lb->next_bio != NULL) 505 lb = lb->next_bio; 506 lb->next_bio = bio; 507 if (bio != NULL) 508 bio->prev_bio = lb; 509 /* called to do internal processing */ 510 BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb); 511 return (b); 512 } 513 514 /* Remove the first and return the rest */ 515 BIO * 516 BIO_pop(BIO *b) 517 { 518 BIO *ret; 519 520 if (b == NULL) 521 return (NULL); 522 ret = b->next_bio; 523 524 BIO_ctrl(b, BIO_CTRL_POP, 0, b); 525 526 if (b->prev_bio != NULL) 527 b->prev_bio->next_bio = b->next_bio; 528 if (b->next_bio != NULL) 529 b->next_bio->prev_bio = b->prev_bio; 530 531 b->next_bio = NULL; 532 b->prev_bio = NULL; 533 return (ret); 534 } 535 536 BIO * 537 BIO_get_retry_BIO(BIO *bio, int *reason) 538 { 539 BIO *b, *last; 540 541 b = last = bio; 542 for (;;) { 543 if (!BIO_should_retry(b)) 544 break; 545 last = b; 546 b = b->next_bio; 547 if (b == NULL) 548 break; 549 } 550 if (reason != NULL) 551 *reason = last->retry_reason; 552 return (last); 553 } 554 555 int 556 BIO_get_retry_reason(BIO *bio) 557 { 558 return (bio->retry_reason); 559 } 560 561 BIO * 562 BIO_find_type(BIO *bio, int type) 563 { 564 int mt, mask; 565 566 if (!bio) 567 return NULL; 568 mask = type & 0xff; 569 do { 570 if (bio->method != NULL) { 571 mt = bio->method->type; 572 if (!mask) { 573 if (mt & type) 574 return (bio); 575 } else if (mt == type) 576 return (bio); 577 } 578 bio = bio->next_bio; 579 } while (bio != NULL); 580 return (NULL); 581 } 582 583 BIO * 584 BIO_next(BIO *b) 585 { 586 if (!b) 587 return NULL; 588 return b->next_bio; 589 } 590 591 void 592 BIO_free_all(BIO *bio) 593 { 594 BIO *b; 595 int ref; 596 597 while (bio != NULL) { 598 b = bio; 599 ref = b->references; 600 bio = bio->next_bio; 601 BIO_free(b); 602 /* Since ref count > 1, don't free anyone else. */ 603 if (ref > 1) 604 break; 605 } 606 } 607 608 BIO * 609 BIO_dup_chain(BIO *in) 610 { 611 BIO *ret = NULL, *eoc = NULL, *bio, *new_bio; 612 613 for (bio = in; bio != NULL; bio = bio->next_bio) { 614 if ((new_bio = BIO_new(bio->method)) == NULL) 615 goto err; 616 new_bio->callback = bio->callback; 617 new_bio->cb_arg = bio->cb_arg; 618 new_bio->init = bio->init; 619 new_bio->shutdown = bio->shutdown; 620 new_bio->flags = bio->flags; 621 622 /* This will let SSL_s_sock() work with stdin/stdout */ 623 new_bio->num = bio->num; 624 625 if (!BIO_dup_state(bio, (char *)new_bio)) { 626 BIO_free(new_bio); 627 goto err; 628 } 629 630 /* copy app data */ 631 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, 632 &new_bio->ex_data, &bio->ex_data)) 633 goto err; 634 635 if (ret == NULL) { 636 eoc = new_bio; 637 ret = eoc; 638 } else { 639 BIO_push(eoc, new_bio); 640 eoc = new_bio; 641 } 642 } 643 return (ret); 644 err: 645 BIO_free(ret); 646 return (NULL); 647 648 } 649 650 void 651 BIO_copy_next_retry(BIO *b) 652 { 653 BIO_set_flags(b, BIO_get_retry_flags(b->next_bio)); 654 b->retry_reason = b->next_bio->retry_reason; 655 } 656 657 int 658 BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 659 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 660 { 661 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp, 662 new_func, dup_func, free_func); 663 } 664 665 int 666 BIO_set_ex_data(BIO *bio, int idx, void *data) 667 { 668 return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data)); 669 } 670 671 void * 672 BIO_get_ex_data(BIO *bio, int idx) 673 { 674 return (CRYPTO_get_ex_data(&(bio->ex_data), idx)); 675 } 676 677 unsigned long 678 BIO_number_read(BIO *bio) 679 { 680 if (bio) 681 return bio->num_read; 682 return 0; 683 } 684 685 unsigned long 686 BIO_number_written(BIO *bio) 687 { 688 if (bio) 689 return bio->num_write; 690 return 0; 691 } 692