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